增加mqtt相关服务,及opus解码
authorhcj <1224667075@qq.com>
Thu, 29 Jan 2026 06:30:30 +0000 (14:30 +0800)
committerhcj <1224667075@qq.com>
Thu, 29 Jan 2026 06:30:30 +0000 (14:30 +0800)
244 files changed:
code/sdk/application/brandy/brandy_standard/CMakeLists.txt
code/sdk/middleware/services/media/foundation/sample/wrapper/audio_manager_c_wrapper.cpp
code/sdk/middleware/services/media/hal/audio/plugins/brandy/primary/primary_sub_port_in.c
code/sdk/zhihui/CMakeLists.txt
code/sdk/zhihui/MQTT/CMakeLists.txt [new file with mode: 0644]
code/sdk/zhihui/MQTT/MQTT_server_mian.c [new file with mode: 0644]
code/sdk/zhihui/MQTT/uapi_Mqtt_api.h [new file with mode: 0644]
code/sdk/zhihui/MQTT/uapi_mqtt.c [new file with mode: 0644]
code/sdk/zhihui/MQTT/uapi_mqtt_at.c [new file with mode: 0644]
code/sdk/zhihui/MQTT/uapi_mqtt_at.h [new file with mode: 0644]
code/sdk/zhihui/ai/media/CMakeLists.txt
code/sdk/zhihui/ai/media/ai_media_service_ext.cpp
code/sdk/zhihui/ai/media/ai_media_service_mqtt.cpp [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/CMakeLists.txt
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_OTA.c [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_UDP.c [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.c [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.h [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.c [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.h [new file with mode: 0644]
code/sdk/zhihui/leiniao/imsl_ln/ln_ota_at.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/BUILD_LIBOPUS.md [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/CLEAN_README.md [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/CMakeLists.txt [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/Makefile [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/Makefile.libopus [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/README.md [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/VERIFY.md [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/build.bat [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/build.sh [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.ps1 [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.sh [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/_kiss_fft_guts.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/arch.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_decoder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/cpu_support.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/ecintrin.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_debug.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_generic.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/float_cast.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/mfrngcod.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/os_support.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/stack_alloc.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed_arm_ne10.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float_arm_ne10.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse4_1.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_avx.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse2.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse4_1.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse2.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_arch_macros.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_celt_map.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.ps1 [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.sh [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/config.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/copy_sources.sh [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_custom.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_defines.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_frame_to_pcm.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_multistream.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_projection.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_types.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/A2NLSF.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/API.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/CNG.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/HP_variable_cutoff.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/Inlines.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_analysis_filter.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_fit.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain_arm.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/LP_variable_cutoff.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroCount.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroDebug.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF2A.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_VQ_weights_laroia.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_decode.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_stabilize.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_unpack.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_del_dec_arm.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_mips.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_neon.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv4.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv5e.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FLP.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt_arm.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander_32.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/code_signs.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/control.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/debug.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/dec_API.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_core.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_frame.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_indices.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_parameters.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pitch.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pulses.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/decoder_set_fs.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/define.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/errors.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_analysis_filter_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_inv_pred_gain_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_analysis_filter_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_scale_ctrl_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/apply_sine_window_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/autocorrelation_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/burg_modified_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/bwexpander_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/corrMatrix_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/encode_frame_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/energy_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LPC_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LTP_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pitch_lags_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pred_coefs_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP_avx2.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/k2a_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/noise_shape_analysis_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/pitch_analysis_core_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/process_gains_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/regularize_correlations_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/residual_energy_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_copy_vector_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_vector_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/schur_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/sort_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/warped_autocorrelation_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/wrappers_FLP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/gain_quant.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/init_decoder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/inner_prod_aligned.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/interpolate.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/lin2log.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/log2lin.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_arm64.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv4.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv5e.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_mipsr1.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/main.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FIX.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FLP.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_defines.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_tables.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2_3.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_AR2.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_IIR_FIR.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_down_FIR.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_up2_HQ.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_structs.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/shell_coder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigm_Q15.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigproc_fix_mipsr1.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/sort.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_MS_to_LR.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_decode_pred.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_find_predictor.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FIX.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FLP.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/sum_sqr_shift.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/table_LSF_cos.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_LTP.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_NB_MB.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_WB.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_gain.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_other.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pitch_lag.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pulses_per_block.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/tuning_parameters.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/typedef.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_arm.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_mipsr1.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/SigProc_FIX_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/main_sse.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/x86_silk_map.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src/opus_frame_to_pcm.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/analysis.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/extensions.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mlp.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_decoder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_multistream_decoder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_private.h [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_projection_decoder.c [new file with mode: 0644]
code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/repacketizer.c [new file with mode: 0644]

index 1680093..f126710 100644 (file)
@@ -45,6 +45,7 @@ set(PRIVATE_HEADER
     ${ROOT_DIR}/zhihui/4g/cat1Service/Service
     ${ROOT_DIR}/zhihui/4gTest
     ${ROOT_DIR}/zhihui/leiniao/imsl_ln/
+    ${ROOT_DIR}/zhihui/leiniao/imsl_ln/LN_MQTT/
 )
 
 set(PUBLIC_HEADER
index dedc718..94f35f0 100644 (file)
@@ -260,6 +260,13 @@ int32_t AudioStreamInDeinit(void)
     return AUDIO_SUCCESS;
 }
 
+int32_t OnRenderCallback(const void *caller, AudioCallbackEventType event, const void *info)
+{
+    (void)info;
+    printf("OnRenderCallback event %d\r\n",event);
+    return 0;
+}
+
 int32_t AudioStreamOutInit(AudioRendererConfig renderConfig)
 {
     g_streamOut = std::make_shared<AudioStreamOut>();
@@ -268,7 +275,7 @@ int32_t AudioStreamOutInit(AudioRendererConfig renderConfig)
         return AUDIO_ERROR;
     }
 
-    int32_t ret = g_streamOut->Init(renderConfig);
+    int32_t ret = g_streamOut->Init(renderConfig,OnRenderCallback);
     if (ret != AUDIO_SUCCESS) {
         ALOGE("audio stream out init failed 0x%x", ret);
         return AUDIO_ERROR;
index 7351283..c95fa13 100644 (file)
@@ -102,6 +102,7 @@ static SubPortTrackInCapabilities g_caps[] = {
     { AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_PCM_16_BIT, 16000, 1},
     { AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_OPUS, 16000, 1 },
     { AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_MP3, 16000, 1 },
+    { AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_SBC, 16000, 1 },
 };
 
 static bool isMultipleAIOpen(void)
index 7db8cfe..7fb9f8a 100644 (file)
@@ -32,4 +32,7 @@ add_subdirectory_if_exist(imsl)
 add_subdirectory_if_exist(minimp3)
 add_subdirectory_if_exist(shake)
 add_subdirectory_if_exist(dmp)
+add_subdirectory_if_exist(MQTT)
+add_subdirectory_if_exist(test_opus_frame_to_pcm)
+
 
diff --git a/code/sdk/zhihui/MQTT/CMakeLists.txt b/code/sdk/zhihui/MQTT/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0d5b48f
--- /dev/null
@@ -0,0 +1,64 @@
+#===============================================================================
+# @brief    MQTT component cmake file
+# Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "mqtt_service")
+
+# 源文件
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/MQTT_server_mian.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/uapi_mqtt.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/uapi_mqtt_at.c
+    ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/apps/mqtt/mqtt.c
+)
+
+# 公共头文件路径(供其他模块引用)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/
+    ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/include
+    ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include
+    ${ROOT_DIR}/open_source/openharmony/third_party/cJSON/
+    ${ROOT_DIR}/zhihui/utils/
+)
+
+# 公共宏定义(可选)
+set(PUBLIC_DEFINES
+    # MQTT服务相关宏定义
+)
+
+# 私有头文件路径(仅当前组件内部使用)
+set(PRIVATE_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/
+)
+
+# 私有宏定义(可选)
+set(PRIVATE_DEFINES
+    # 如无特殊私有宏,可留空
+)
+
+# 公共编译选项(可选)
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+# 组件专属编译选项
+set(COMPONENT_CCFLAGS
+    -Wno-incompatible-function-pointer-types
+    -Wno-unused-function  # 屏蔽未使用函数的警告(根据实际情况调整)
+)
+
+# 是否启用全量链接(静态库通常需要)
+set(WHOLE_LINK
+    true
+)
+
+# 是否为主组件(通常为false,主组件一般是app)
+set(MAIN_COMPONENT
+    false
+)
+
+# 安装SDK时包含的文件(头文件和库文件)
+install_sdk(${CMAKE_CURRENT_SOURCE_DIR} "*")
+
+# 构建组件
+build_component()
+
diff --git a/code/sdk/zhihui/MQTT/MQTT_server_mian.c b/code/sdk/zhihui/MQTT/MQTT_server_mian.c
new file mode 100644 (file)
index 0000000..771ce0a
--- /dev/null
@@ -0,0 +1,817 @@
+#include "custom_utils.h"
+#include "cmsis_os2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <linux/delay.h>
+#include "uapi_Mqtt_api.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+extern mqtt_log_level_t g_mqtt_log_level ;
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+/* MQTT消息类型定义 */
+#define MQTT_MSG_TYPE_SEND       0x01  // 发送消息
+#define MQTT_MSG_TYPE_RECV       0x02  // 接收消息
+#define MQTT_MSG_TYPE_STOP       0x03  // 停止线程
+#define MQTT_MSG_TYPE_CONNECT    0x04  // 连接请求
+#define MQTT_MSG_TYPE_DISCONNECT 0x05  // 断开请求
+#define MQTT_MSG_TYPE_SUBSCRIBE  0x06  // 订阅结果
+
+/* MQTT连接状态 */
+#define MQTT_STATE_DISCONNECTED  0
+#define MQTT_STATE_CONNECTING    1
+#define MQTT_STATE_CONNECTED     2
+#define MQTT_STATE_RECONNECTING  3
+
+/* MQTT消息队列大小 */
+#define MQTT_SEND_QUEUE_COUNT    64
+#define MQTT_RECV_QUEUE_COUNT    64
+
+/* MQTT发送消息结构体 */
+typedef struct {
+    char topic[256];
+    uint8_t *payload;
+    uint16_t payload_len;
+    uint8_t qos;
+    uint8_t retain;
+} mqtt_send_msg_t;
+
+/* MQTT接收消息结构体 */
+typedef struct {
+    char topic[256];
+    uint8_t *data;
+    uint16_t data_len;
+} mqtt_recv_msg_t;
+
+/* MQTT订阅结果消息结构体 */
+typedef struct {
+    char topic[256];
+    uint8_t qos;
+    int result;  // 0表示成功,非0表示失败
+} mqtt_subscribe_msg_t;
+
+/* MQTT消息结构体(用于队列) */
+typedef struct {
+    uint8_t msg_type;
+    union {
+        mqtt_send_msg_t send_msg;
+        mqtt_recv_msg_t recv_msg;
+        mqtt_subscribe_msg_t subscribe_msg;
+    } msg;
+} mqtt_queue_msg_t;
+
+/* 全局变量 */
+static volatile int g_mqtt_thread_running = 0;
+static uint32_t g_mqtt_send_thread_handle = 0;
+static uint32_t g_mqtt_main_thread_handle = 0;
+static osMessageQueueId_t g_mqtt_send_queue = NULL;  // 发送队列(发送消息,由发送线程处理)
+static osMessageQueueId_t g_mqtt_recv_queue = NULL;  // 接收队列(接收消息,由主线程处理)
+static volatile int g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+static volatile int g_mqtt_connection_status = -1;  // 连接状态码(-1表示未初始化,0表示连接成功,其他值表示错误码)
+static volatile int g_mqtt_last_connection_status = -1;  // 上一次的连接状态码,用于检测状态变化
+static uint32_t g_mqtt_reconnect_count = 0;
+static uint32_t g_mqtt_last_connect_attempt = 0;
+static mqtt_call_backs_t g_mqtt_callbacks = {0};  // MQTT回调函数结构体
+static uint32_t g_main_thread_interval_ms = 1000;  // 主线程循环间隔时长(毫秒),默认1000ms
+#define MQTT_RECONNECT_INTERVAL_MS 5000  // 重连间隔5秒
+
+/* 前向声明 */
+static void mqtt_send_thread(void *arg);
+static void mqtt_main_thread(void *arg);
+static void mqtt_queue_init(void);
+static void mqtt_send_queue_init(void);
+static void mqtt_recv_queue_init(void);
+static void mqtt_main_queue_init(void);
+static int mqtt_try_connect(void);
+static void mqtt_connection_status_cb(void *arg, int status);
+
+/**
+ * @brief 初始化发送队列
+ */
+static void mqtt_send_queue_init(void)
+{
+    MQTT_DEBUG("Initializing send queue\n");
+    g_mqtt_send_queue = osMessageQueueNew(MQTT_SEND_QUEUE_COUNT, sizeof(mqtt_queue_msg_t*), NULL);
+    if (g_mqtt_send_queue == NULL) {
+        MQTT_ERROR("Failed to create send queue\n");
+    } else {
+        MQTT_DEBUG("Send queue created successfully\n");
+    }
+}
+
+/**
+ * @brief 初始化接收队列
+ */
+static void mqtt_recv_queue_init(void)
+{
+    MQTT_DEBUG("Initializing recv queue\n");
+    g_mqtt_recv_queue = osMessageQueueNew(MQTT_RECV_QUEUE_COUNT, sizeof(mqtt_queue_msg_t*), NULL);
+    if (g_mqtt_recv_queue == NULL) {
+        MQTT_ERROR("Failed to create recv queue\n");
+    } else {
+        MQTT_DEBUG("Recv queue created successfully\n");
+    }
+}
+
+/**
+ * @brief 初始化主线程队列(用于连接管理)
+ */
+static void mqtt_main_queue_init(void)
+{
+    // 主线程使用发送队列处理命令消息,不需要单独创建
+    MQTT_DEBUG("Main thread queue initialized\n");
+}
+
+/**
+ * @brief 初始化队列(统一接口)
+ */
+static void mqtt_queue_init(void)
+{
+    mqtt_send_queue_init();
+    mqtt_recv_queue_init();
+    mqtt_main_queue_init();
+}
+
+/**
+ * @brief MQTT连接状态回调(用于主线程)
+ * 只更新全局状态变量,由主线程循环检测状态变化并触发用户回调
+ */
+static void mqtt_connection_status_cb(void *arg, int status)
+{
+    (void)arg;
+    MQTT_DEBUG("Connection status callback: %d\n", status);
+    
+    // 更新连接状态码
+    g_mqtt_connection_status = status;
+    
+    if (status == 0) {  // MQTT_CONNECT_ACCEPTED
+        g_mqtt_connection_state = MQTT_STATE_CONNECTED;
+        g_mqtt_reconnect_count = 0;
+        MQTT_INFO("MQTT connected successfully\n");
+    } else {
+        g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+        MQTT_INFO("MQTT disconnected, status: %d\n", status);
+    }
+}
+
+/**
+ * @brief MQTT消息接收回调(用于主线程)
+ * 将接收到的消息放入接收队列(用户回调将在队列读取时触发)
+ */
+static void mqtt_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+    (void)arg;
+    
+    MQTT_DEBUG("Message received callback: topic=%s, len=%d\n", topic ? topic : "NULL", len);
+
+
+    
+    
+    // 将接收到的消息放入接收队列(用户回调将在主线程从队列读取时触发)
+    if (topic && data && len > 0) {
+        int ret = uapi_mqtt_main_recv_enqueue(topic, data, len);
+        if (ret != 0) {
+            MQTT_ERROR("Failed to enqueue received message\n");
+        }
+    }
+}
+
+/**
+ * @brief 尝试连接MQTT服务器
+ */
+static int mqtt_try_connect(void)
+{
+    if (g_mqtt_connection_state == MQTT_STATE_CONNECTING || 
+        g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+        return 0;  // 正在连接或已连接
+    }
+    
+    MQTT_INFO("Attempting to connect MQTT server\n");
+    g_mqtt_connection_state = MQTT_STATE_CONNECTING;
+    g_mqtt_last_connect_attempt = osKernelGetTickCount();
+    
+    // 初始化MQTT客户端
+    if (uapi_mqtt_init() != 0) {
+        MQTT_ERROR("Failed to initialize MQTT client\n");
+        g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+        return -1;
+    }
+    
+    // 尝试通过回调获取凭证
+    mqtt_credentials_t credentials = {0};
+    const mqtt_credentials_t *use_cred = NULL;
+    
+    if (g_mqtt_callbacks.credentials_callback != NULL) {
+        MQTT_DEBUG("Getting credentials from callback\n");
+        if (g_mqtt_callbacks.credentials_callback(g_mqtt_callbacks.user_arg, &credentials) == 0) {
+            // 检查凭证是否有效
+            if (credentials.endpoint[0] != '\0' && credentials.client_id[0] != '\0') {
+                use_cred = &credentials;
+                MQTT_DEBUG("Credentials obtained from callback\n");
+            } else {
+                MQTT_WARN("Invalid credentials from callback, will load from file\n");
+            }
+        } else {
+            MQTT_WARN("Credentials callback returned error, will load from file\n");
+        }
+    }
+    
+    // 如果回调未提供凭证,则从文件加载(NULL表示从文件加载)
+    // 连接MQTT服务器
+    int ret = uapi_mqtt_connect(use_cred, mqtt_connection_status_cb, mqtt_message_cb, NULL);
+    if (ret != 0) {
+        MQTT_ERROR("Failed to initiate MQTT connection: %d\n", ret);
+        g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+        return -1;
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief MQTT发送线程
+ */
+static void mqtt_send_thread(void *arg)
+{
+    (void)arg;
+    mqtt_queue_msg_t *msg = NULL;
+    
+    MQTT_INFO("Send thread started\n");
+    
+    while (g_mqtt_thread_running) {
+        // 从发送队列获取消息(阻塞等待,超时100ms)
+        osStatus_t status = osMessageQueueGet(g_mqtt_send_queue, &msg, NULL, 100);
+        
+        if (status == osOK && msg != NULL) {
+            if (msg->msg_type == MQTT_MSG_TYPE_STOP) {
+                MQTT_DEBUG("Send thread received stop signal\n");
+                free(msg);
+                break;
+            }
+            
+            // 发送线程只处理发送消息类型
+            if (msg->msg_type == MQTT_MSG_TYPE_SEND) {
+                // 检查连接状态
+                if (uapi_mqtt_is_connected()) {
+                    MQTT_DEBUG("Sending message to topic: %s, len: %d\n", 
+                           msg->msg.send_msg.topic, msg->msg.send_msg.payload_len);
+                    
+                    int ret = uapi_mqtt_publish(msg->msg.send_msg.topic,
+                                            msg->msg.send_msg.payload,
+                                            msg->msg.send_msg.payload_len,
+                                            msg->msg.send_msg.qos,
+                                            msg->msg.send_msg.retain);
+                    if (ret != 0) {
+                        MQTT_ERROR("Failed to publish message: %d\n", ret);
+                    }
+                } else {
+                    MQTT_WARN("MQTT not connected, message dropped\n");
+                }
+                
+                // 释放消息内存
+                if (msg->msg.send_msg.payload != NULL) {
+                    free(msg->msg.send_msg.payload);
+                }
+                
+                free(msg);
+                msg = NULL;
+            } else {
+                // 其他消息类型(命令消息)主线程不再处理,直接释放
+                MQTT_WARN("Send thread: Unknown message type %d, dropping\n", msg->msg_type);
+                free(msg);
+                msg = NULL;
+            }
+        }
+    }
+    
+    MQTT_INFO("Send thread exited\n");
+}
+
+
+/**
+ * @brief MQTT主线程(管理连接状态、重连等)
+ */
+static void mqtt_main_thread(void *arg)
+{
+    (void)arg;
+    mqtt_queue_msg_t *msg = NULL;
+    int last_connection_state = MQTT_STATE_DISCONNECTED;
+    
+    MQTT_INFO("Main thread started\n");
+    
+    // 初始化上一次的连接状态码
+    g_mqtt_last_connection_status = g_mqtt_connection_status;
+    
+    // 尝试首次连接(mqtt_try_connect内部会初始化)
+    mqtt_try_connect();
+    
+    while (g_mqtt_thread_running) {
+        // 处理接收队列中的接收消息(非阻塞)
+        if (osMessageQueueGet(g_mqtt_recv_queue, &msg, NULL, 0) == osOK) {
+            if (msg != NULL) {
+                if (msg->msg_type == MQTT_MSG_TYPE_RECV) {
+                    MQTT_DEBUG("Received message from topic: %s, len: %d\n",
+                           msg->msg.recv_msg.topic, msg->msg.recv_msg.data_len);
+                    
+                    // 处理接收到的消息
+                    if (msg->msg.recv_msg.data != NULL && msg->msg.recv_msg.data_len > 0) {
+                        // 打印消息内容(限制长度)
+                        MQTT_DEBUG("Message content: ");
+                        uint16_t print_len = msg->msg.recv_msg.data_len > 100 ? 100 : msg->msg.recv_msg.data_len;
+                        for (uint16_t i = 0; i < print_len; i++) {
+                            uint8_t c = msg->msg.recv_msg.data[i];
+                            if (c >= 32 && c < 127) {
+                                printf("%c", c);
+                            } else {
+                                printf(".");
+                            }
+                        }
+                        if (msg->msg.recv_msg.data_len > 100) {
+                            printf("...");
+                        }
+                        printf("\n");
+                        
+                        // 调用用户注册的消息回调(在队列读取时触发)
+                        if (g_mqtt_callbacks.message_callback != NULL) {
+                            g_mqtt_callbacks.message_callback(g_mqtt_callbacks.user_arg, 
+                                                              msg->msg.recv_msg.topic, 
+                                                              msg->msg.recv_msg.data, 
+                                                              msg->msg.recv_msg.data_len);
+                        }
+                        
+                        // 这里可以添加更多消息处理逻辑
+                        // 例如:解析JSON、路由到不同的处理函数等
+                    }
+                    
+                    // 释放消息内存
+                    if (msg->msg.recv_msg.data != NULL) {
+                        free(msg->msg.recv_msg.data);
+                    }
+                } else if (msg->msg_type == MQTT_MSG_TYPE_SUBSCRIBE) {
+                    // 处理订阅结果消息(在主线程中触发用户回调)
+                    MQTT_DEBUG("Subscribe result - Topic: %s, QoS: %d, Result: %d\n",
+                           msg->msg.subscribe_msg.topic, 
+                           msg->msg.subscribe_msg.qos, 
+                           msg->msg.subscribe_msg.result);
+                    
+                    // 调用用户注册的订阅回调(在主线程中触发)
+                    if (g_mqtt_callbacks.subscribe_callback != NULL) {
+                        g_mqtt_callbacks.subscribe_callback(g_mqtt_callbacks.user_arg,
+                                                             msg->msg.subscribe_msg.topic,
+                                                             msg->msg.subscribe_msg.qos,
+                                                             msg->msg.subscribe_msg.result);
+                    }
+                } else {
+                    MQTT_WARN("Unknown message type in recv queue: %d\n", msg->msg_type);
+                }
+                
+                free(msg);
+                msg = NULL;
+            }
+        }
+        
+        // 检测连接状态码变化(在主线程循环中检测并触发用户回调)
+        if (g_mqtt_connection_status != g_mqtt_last_connection_status) {
+            int current_status = g_mqtt_connection_status;
+            int last_status = g_mqtt_last_connection_status;
+            
+            MQTT_DEBUG("Connection status changed in main thread: %d -> %d\n", 
+                   last_status, current_status);
+            
+            // 更新上一次的状态码
+            g_mqtt_last_connection_status = current_status;
+            
+            // 调用用户注册的连接回调(在主线程循环中触发)
+            if (g_mqtt_callbacks.connect_callback != NULL) {
+                g_mqtt_callbacks.connect_callback(g_mqtt_callbacks.user_arg, current_status);
+            }
+        }
+        
+        // 检测连接状态变化(用于日志输出)
+        if (g_mqtt_connection_state != last_connection_state) {
+            MQTT_DEBUG("Connection state changed: %d -> %d\n", 
+                   last_connection_state, g_mqtt_connection_state);
+            last_connection_state = g_mqtt_connection_state;
+        }
+        
+        // 连接管理:检查连接状态并处理重连
+        if (g_mqtt_connection_state == MQTT_STATE_DISCONNECTED) {
+            // 检查是否需要重连
+            uint32_t current_tick = osKernelGetTickCount();
+            uint32_t elapsed_ticks = 0;
+            
+            if (current_tick >= g_mqtt_last_connect_attempt) {
+                elapsed_ticks = current_tick - g_mqtt_last_connect_attempt;
+            } else {
+                // 处理tick溢出
+                elapsed_ticks = (UINT32_MAX - g_mqtt_last_connect_attempt) + current_tick;
+            }
+            
+            // 将tick转换为毫秒(使用osKernelGetTickFreq获取tick频率)
+            uint32_t tick_freq = osKernelGetTickFreq();
+            uint32_t elapsed_ms = (elapsed_ticks * 1000) / (tick_freq > 0 ? tick_freq : 100);
+            
+            if (elapsed_ms >= MQTT_RECONNECT_INTERVAL_MS) {
+                g_mqtt_reconnect_count++;
+                MQTT_INFO("Attempting reconnect #%u\n", g_mqtt_reconnect_count);
+                mqtt_try_connect();
+            }
+        } else if (g_mqtt_connection_state == MQTT_STATE_CONNECTING) {
+            // 检查连接超时(30秒)
+            uint32_t current_tick = osKernelGetTickCount();
+            uint32_t elapsed_ticks = 0;
+            
+            if (current_tick >= g_mqtt_last_connect_attempt) {
+                elapsed_ticks = current_tick - g_mqtt_last_connect_attempt;
+            } else {
+                elapsed_ticks = (UINT32_MAX - g_mqtt_last_connect_attempt) + current_tick;
+            }
+            
+            // 将tick转换为毫秒
+            uint32_t tick_freq = osKernelGetTickFreq();
+            uint32_t elapsed_ms = (elapsed_ticks * 1000) / (tick_freq > 0 ? tick_freq : 100);
+            uint32_t timeout_ms = 30000;
+            
+            if (elapsed_ms >= timeout_ms) {
+                MQTT_WARN("Connection timeout, resetting state\n");
+                g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+                uapi_mqtt_disconnect();
+            }
+        }
+        
+        // 检查实际连接状态(与状态标志同步)
+        bool actual_connected = uapi_mqtt_is_connected();
+        if (actual_connected && g_mqtt_connection_state != MQTT_STATE_CONNECTED) {
+            g_mqtt_connection_state = MQTT_STATE_CONNECTED;
+            MQTT_DEBUG("Connection state synchronized to CONNECTED\n");
+        } else if (!actual_connected && g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+            g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+            MQTT_DEBUG("Connection state synchronized to DISCONNECTED\n");
+        }
+        
+        // 延迟,避免CPU占用过高(使用配置的间隔时长)
+        msleep(g_main_thread_interval_ms);
+    }
+    
+        // 清理:断开MQTT连接
+        if (g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+            uapi_mqtt_disconnect();
+        }
+        uapi_mqtt_deinit();
+    g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+    
+    MQTT_INFO("Main thread exited\n");
+}
+
+/**
+ * @brief 启动MQTT发送和接收线程
+ * @param callbacks MQTT回调函数结构体(可以为NULL,使用默认处理)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_start(const mqtt_call_backs_t *callbacks)
+{
+    if (g_mqtt_thread_running) {
+        MQTT_INFO("Threads already running\n");
+        return 0;
+    }
+    
+    g_mqtt_thread_running = 1;
+    g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+    g_mqtt_reconnect_count = 0;
+    
+    // 注册回调函数结构体
+    if (callbacks != NULL) {
+        g_mqtt_callbacks = *callbacks;
+        
+        // 设置主线程间隔时长,如果未设置则使用默认值
+        if (g_mqtt_callbacks.main_thread_interval_ms > 0) {
+            g_main_thread_interval_ms = g_mqtt_callbacks.main_thread_interval_ms;
+        } else {
+            g_main_thread_interval_ms = 1000; // 默认1000ms
+        }
+        
+        MQTT_INFO("MQTT callbacks registered successfully, main thread interval: %u ms\n", g_main_thread_interval_ms);
+        
+        if (g_mqtt_callbacks.connect_callback != NULL) {
+            MQTT_DEBUG("Connect callback registered\n");
+        } else {
+            MQTT_DEBUG("No connect callback registered\n");
+        }
+        
+        if (g_mqtt_callbacks.message_callback != NULL) {
+            MQTT_DEBUG("Message callback registered\n");
+        } else {
+            MQTT_DEBUG("No message callback registered\n");
+        }
+        
+        if (g_mqtt_callbacks.credentials_callback != NULL) {
+            MQTT_DEBUG("Credentials callback registered\n");
+        } else {
+            MQTT_DEBUG("No credentials callback registered (will load from file)\n");
+        }
+    } else {
+        memset(&g_mqtt_callbacks, 0, sizeof(mqtt_call_backs_t));
+        g_main_thread_interval_ms = 1000; // 默认1000ms
+        MQTT_INFO("No callbacks provided, using defaults\n");
+    }
+    
+    // 初始化队列
+    mqtt_queue_init();
+    
+    // 创建主线程(管理连接状态和接收消息)
+    {
+        app_task_definition_ext_t main_task = {
+            .attr = {
+                .name = "uapi_mqtt_main",
+                .stack_size = 0x2000,
+                .priority = osPriorityNormal
+            },
+            .func = mqtt_main_thread,
+            .task_handle = &g_mqtt_main_thread_handle,
+            .create_queue_handle = mqtt_main_queue_init,
+            .use_mem = USE_EXTEND_MEM,
+            .inst_args = NULL
+        };
+        
+        errcode_t ret = uapi_create_osThread_custom_with_args(&main_task);
+        if (ret != ERRCODE_SUCC) {
+            MQTT_ERROR("Failed to create main thread: %d\n", ret);
+            g_mqtt_thread_running = 0;
+            return -1;
+        }
+        MQTT_INFO("Main thread created successfully\n");
+    }
+    
+    // 创建发送线程(处理发送消息)
+    {
+        app_task_definition_ext_t send_task = {
+            .attr = {
+                .name = "uapi_mqtt_send",
+                .stack_size = 0x2000,
+                .priority = osPriorityNormal
+            },
+            .func = mqtt_send_thread,
+            .task_handle = &g_mqtt_send_thread_handle,
+            .create_queue_handle = NULL,  // 发送队列已初始化,不需要单独创建
+            .use_mem = USE_EXTEND_MEM,
+            .inst_args = NULL
+        };
+        
+        errcode_t ret = uapi_create_osThread_custom_with_args(&send_task);
+        if (ret != ERRCODE_SUCC) {
+            MQTT_ERROR("Failed to create send thread: %d\n", ret);
+            g_mqtt_thread_running = 0;
+            return -1;
+        }
+        MQTT_INFO("Send thread created successfully\n");
+    }
+    
+    MQTT_INFO("MQTT threads started successfully\n");
+    return 0;
+}
+
+/**
+ * @brief 停止MQTT发送和接收线程
+ */
+void uapi_mqtt_main_stop(void)
+{
+    if (!g_mqtt_thread_running) {
+        return;
+    }
+    
+    MQTT_INFO("Stopping MQTT threads\n");
+    g_mqtt_thread_running = 0;
+    
+    // 断开MQTT连接
+    if (g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+        uapi_mqtt_disconnect();
+    }
+    
+    // 发送停止消息到发送队列(主线程和发送线程都会处理)
+    if (g_mqtt_send_queue != NULL) {
+        mqtt_queue_msg_t *stop_msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+        if (stop_msg != NULL) {
+            stop_msg->msg_type = MQTT_MSG_TYPE_STOP;
+            osMessageQueuePut(g_mqtt_send_queue, &stop_msg, 0, 0);
+        }
+    }
+    
+    // 等待线程退出(最多等待2秒)
+    int wait_count = 0;
+    while ((g_mqtt_main_thread_handle != 0 || g_mqtt_send_thread_handle != 0) && wait_count < 200) {
+        msleep(10);
+        wait_count++;
+    }
+    
+    // 清理发送队列中的剩余消息
+    if (g_mqtt_send_queue != NULL) {
+        mqtt_queue_msg_t *msg = NULL;
+        while (osMessageQueueGet(g_mqtt_send_queue, &msg, NULL, 0) == osOK) {
+            if (msg != NULL) {
+                if (msg->msg_type == MQTT_MSG_TYPE_SEND && msg->msg.send_msg.payload != NULL) {
+                    free(msg->msg.send_msg.payload);
+                }
+                free(msg);
+            }
+        }
+        osMessageQueueDelete(g_mqtt_send_queue);
+        g_mqtt_send_queue = NULL;
+    }
+    
+    // 清理接收队列中的剩余消息
+    if (g_mqtt_recv_queue != NULL) {
+        mqtt_queue_msg_t *msg = NULL;
+        while (osMessageQueueGet(g_mqtt_recv_queue, &msg, NULL, 0) == osOK) {
+            if (msg != NULL) {
+                if (msg->msg_type == MQTT_MSG_TYPE_RECV && msg->msg.recv_msg.data != NULL) {
+                    free(msg->msg.recv_msg.data);
+                }
+                free(msg);
+            }
+        }
+        osMessageQueueDelete(g_mqtt_recv_queue);
+        g_mqtt_recv_queue = NULL;
+    }
+    
+    g_mqtt_main_thread_handle = 0;
+    g_mqtt_send_thread_handle = 0;
+    g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+    
+    // 清空回调函数结构体
+    memset(&g_mqtt_callbacks, 0, sizeof(mqtt_call_backs_t));
+    
+    MQTT_INFO("MQTT threads stopped\n");
+}
+
+/**
+ * @brief 发送MQTT消息到队列
+ * @param topic 主题名称
+ * @param payload 消息内容
+ * @param payload_len 消息长度
+ * @param qos QoS等级
+ * @param retain 保留标志
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_send(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain)
+{
+    if (!g_mqtt_thread_running || g_mqtt_send_queue == NULL) {
+        MQTT_WARN("Send queue not available\n");
+        return -1;
+    }
+    
+    if (!topic || !payload || payload_len == 0) {
+        MQTT_ERROR("Invalid parameters\n");
+        return -1;
+    }
+    
+    // 分配消息结构体
+    mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+    if (msg == NULL) {
+        MQTT_ERROR("Failed to allocate message\n");
+        return -1;
+    }
+    
+    memset(msg, 0, sizeof(mqtt_queue_msg_t));
+    msg->msg_type = MQTT_MSG_TYPE_SEND;
+    
+    // 复制主题
+    strncpy(msg->msg.send_msg.topic, topic, sizeof(msg->msg.send_msg.topic) - 1);
+    msg->msg.send_msg.topic[sizeof(msg->msg.send_msg.topic) - 1] = '\0';
+    
+    // 分配并复制payload
+    msg->msg.send_msg.payload = (uint8_t *)malloc(payload_len);
+    if (msg->msg.send_msg.payload == NULL) {
+        MQTT_ERROR("Failed to allocate payload\n");
+        free(msg);
+        return -1;
+    }
+    memcpy(msg->msg.send_msg.payload, payload, payload_len);
+    
+    msg->msg.send_msg.payload_len = payload_len;
+    msg->msg.send_msg.qos = qos;
+    msg->msg.send_msg.retain = retain;
+    
+    // 将消息放入发送队列
+    osStatus_t status = osMessageQueuePut(g_mqtt_send_queue, &msg, 0, 0);
+    if (status != osOK) {
+        MQTT_ERROR("Failed to put message to queue: %d\n", status);
+        free(msg->msg.send_msg.payload);
+        free(msg);
+        return -1;
+    }
+    
+    MQTT_DEBUG("Message queued for sending: topic=%s, len=%d\n", topic, payload_len);
+    return 0;
+}
+
+/**
+ * @brief 将订阅结果消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_subscribe_enqueue(const char *topic, uint8_t qos, int result)
+{
+    if (!g_mqtt_thread_running || g_mqtt_recv_queue == NULL) {
+        return -1;
+    }
+    
+    if (!topic) {
+        return -1;
+    }
+    
+    // 分配消息结构体
+    mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+    if (msg == NULL) {
+        return -1;
+    }
+    
+    memset(msg, 0, sizeof(mqtt_queue_msg_t));
+    msg->msg_type = MQTT_MSG_TYPE_SUBSCRIBE;
+    
+    // 复制主题
+    strncpy(msg->msg.subscribe_msg.topic, topic, sizeof(msg->msg.subscribe_msg.topic) - 1);
+    msg->msg.subscribe_msg.topic[sizeof(msg->msg.subscribe_msg.topic) - 1] = '\0';
+    
+    // 设置QoS和结果
+    msg->msg.subscribe_msg.qos = qos;
+    msg->msg.subscribe_msg.result = result;
+    
+    // 将消息放入接收队列
+    osStatus_t status = osMessageQueuePut(g_mqtt_recv_queue, &msg, 0, 0);
+    if (status != osOK) {
+        MQTT_ERROR("Failed to put subscribe message to queue: %d\n", status);
+        free(msg);
+        return -1;
+    }
+    
+    MQTT_DEBUG("Subscribe message queued: topic=%s, qos=%d, result=%d\n", topic, qos, result);
+    return 0;
+}
+
+/**
+ * @brief 将接收到的MQTT消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param data 消息数据
+ * @param data_len 消息长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len)
+{
+    if (!g_mqtt_thread_running || g_mqtt_recv_queue == NULL) {
+        return -1;
+    }
+    
+    if (!topic || !data || data_len == 0) {
+        return -1;
+    }
+    
+    // 分配消息结构体
+    mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+    if (msg == NULL) {
+        return -1;
+    }
+    
+    memset(msg, 0, sizeof(mqtt_queue_msg_t));
+    msg->msg_type = MQTT_MSG_TYPE_RECV;
+    
+    // 复制主题
+    strncpy(msg->msg.recv_msg.topic, topic, sizeof(msg->msg.recv_msg.topic) - 1);
+    msg->msg.recv_msg.topic[sizeof(msg->msg.recv_msg.topic) - 1] = '\0';
+    
+    // 分配并复制数据
+    msg->msg.recv_msg.data = (uint8_t *)malloc(data_len);
+    if (msg->msg.recv_msg.data == NULL) {
+        free(msg);
+        return -1;
+    }
+    memcpy(msg->msg.recv_msg.data, data, data_len);
+    
+    msg->msg.recv_msg.data_len = data_len;
+    
+    // 将消息放入队列
+    osStatus_t status = osMessageQueuePut(g_mqtt_recv_queue, &msg, 0, 0);
+    if (status != osOK) {
+        free(msg->msg.recv_msg.data);
+        free(msg);
+        return -1;
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 获取MQTT连接状态
+ * @return 连接状态(MQTT_STATE_DISCONNECTED/MQTT_STATE_CONNECTING/MQTT_STATE_CONNECTED)
+ */
+int uapi_mqtt_main_get_state(void)
+{
+    return g_mqtt_connection_state;
+}
+
diff --git a/code/sdk/zhihui/MQTT/uapi_Mqtt_api.h b/code/sdk/zhihui/MQTT/uapi_Mqtt_api.h
new file mode 100644 (file)
index 0000000..2b951d2
--- /dev/null
@@ -0,0 +1,220 @@
+#ifndef UAPI_MQTT_H
+#define UAPI_MQTT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lwip/apps/mqtt.h"
+
+/* ==================== MQTT 统一日志系统 ==================== */
+/* 日志等级枚举 */
+typedef enum {
+    MQTT_LOG_ERROR = 0,    // 错误信息
+    MQTT_LOG_WARN = 1,     // 警告信息
+    MQTT_LOG_INFO = 2,     // 一般信息
+    MQTT_LOG_DEBUG = 3     // 调试信息
+} mqtt_log_level_t;
+
+/* 日志等级字符串数组 */
+#define MQTT_LOG_LEVEL_STR_ERROR "[ERROR]"
+#define MQTT_LOG_LEVEL_STR_WARN  "[WARN]"
+#define MQTT_LOG_LEVEL_STR_INFO  "[INFO]"
+#define MQTT_LOG_LEVEL_STR_DEBUG "[DEBUG]"
+
+/* 日志宏定义(需要在 .c 文件中定义 g_mqtt_log_level 变量) */
+#define MQTT_LOG(level, line, fmt, ...) do { \
+    extern mqtt_log_level_t g_mqtt_log_level; \
+    if (level <= g_mqtt_log_level) { \
+        const char *level_str = (level == MQTT_LOG_ERROR) ? MQTT_LOG_LEVEL_STR_ERROR : \
+                               (level == MQTT_LOG_WARN) ? MQTT_LOG_LEVEL_STR_WARN : \
+                               (level == MQTT_LOG_INFO) ? MQTT_LOG_LEVEL_STR_INFO : \
+                               MQTT_LOG_LEVEL_STR_DEBUG; \
+        printf("[MQTT]%s " fmt, level_str, ##__VA_ARGS__); \
+    } \
+} while(0)
+
+/* 便捷打印宏 */
+#define MQTT_ERROR(fmt, ...) MQTT_LOG(MQTT_LOG_ERROR, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_WARN(fmt, ...)  MQTT_LOG(MQTT_LOG_WARN, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_INFO(fmt, ...)  MQTT_LOG(MQTT_LOG_INFO, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_DEBUG(fmt, ...) MQTT_LOG(MQTT_LOG_DEBUG, __LINE__, fmt, ##__VA_ARGS__)
+
+/* 设置日志等级函数声明 */
+void mqtt_set_log_level(uint8_t level);
+/* ==================== MQTT 统一日志系统结束 ==================== */
+
+// /* 前向声明 */
+// struct mqtt_client;
+// typedef struct mqtt_client mqtt_client_t;
+
+/* MQTT 凭证结构体(与ln_OTA.c中的定义保持一致) */
+typedef struct {
+    char endpoint[256];
+    char client_id[256];
+    char username[256];
+    char password[256];
+    char publish_topic[128];
+    char subscribe_topic[128];
+} mqtt_credentials_t;
+
+/* MQTT 连接状态回调函数类型 */
+typedef void (*uapi_mqtt_connect_cb_t)(void *arg, int status);
+
+/* MQTT 消息接收回调函数类型 */
+typedef void (*uapi_mqtt_message_cb_t)(void *arg, const char *topic, const uint8_t *data, uint16_t len);
+
+/* MQTT 凭证获取回调函数类型 */
+/* @param arg 用户参数
+ * @param cred 输出的MQTT凭证结构体指针(由回调函数填充)
+ * @return 0 成功填充凭证,-1 失败或未提供凭证(将使用默认方式从文件加载)
+ */
+typedef int (*uapi_mqtt_credentials_cb_t)(void *arg, mqtt_credentials_t *cred);
+
+/* MQTT 订阅结果回调函数类型 */
+/* @param arg 用户参数
+ * @param topic 订阅的主题
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ */
+typedef void (*uapi_mqtt_subscribe_cb_t)(void *arg, const char *topic, uint8_t qos, int result);
+
+/* MQTT回调函数结构体 */
+typedef struct {
+    uapi_mqtt_connect_cb_t connect_callback;      /* 连接状态回调函数 */
+    uapi_mqtt_message_cb_t message_callback;    /* 消息接收回调函数 */
+    uapi_mqtt_credentials_cb_t credentials_callback; /* 凭证获取回调函数 */
+    uapi_mqtt_subscribe_cb_t subscribe_callback; /* 订阅结果回调函数 */
+    void *user_arg;                              /* 用户参数(传递给回调函数) */
+    uint32_t main_thread_interval_ms;            /* 主线程循环间隔时长(毫秒),默认1000ms */
+} mqtt_call_backs_t;
+
+/**
+ * @brief 初始化MQTT客户端
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_init(void);
+
+/**
+ * @brief 反初始化MQTT客户端
+ */
+void uapi_mqtt_deinit(void);
+
+/**
+ * @brief 从文件加载MQTT凭证
+ * @param cred 输出的MQTT凭证结构体指针
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_load_credentials(mqtt_credentials_t *cred);
+
+/**
+ * @brief 连接MQTT服务器
+ * @param cred MQTT凭证(如果为NULL,将从文件加载)
+ * @param connect_cb 连接状态回调函数
+ * @param message_cb 消息接收回调函数
+ * @param arg 回调函数参数
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_connect(const mqtt_credentials_t *cred, 
+                      uapi_mqtt_connect_cb_t connect_cb,
+                      uapi_mqtt_message_cb_t message_cb,
+                      void *arg);
+
+/**
+ * @brief 断开MQTT连接
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_disconnect(void);
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool uapi_mqtt_is_connected(void);
+
+/**
+ * @brief 订阅主题
+ * @param topic 主题名称
+ * @param qos QoS等级(0-2)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_subscribe(const char *topic, uint8_t qos);
+
+/**
+ * @brief 取消订阅主题
+ * @param topic 主题名称
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_unsubscribe(const char *topic);
+
+/**
+ * @brief 获取当前连接的publish_topic(内部使用,供上层API调用)
+ * @param publish_topic 输出的publish_topic缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败(如果未设置,返回-1但不表示错误)
+ */
+int uapi_mqtt_get_publish_topic(char *publish_topic, size_t len);
+
+/**
+ * @brief 启动MQTT发送和接收线程
+ * @param callbacks MQTT回调函数结构体(可以为NULL,使用默认处理)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_start(const mqtt_call_backs_t *callbacks);
+
+/**
+ * @brief 停止MQTT发送和接收线程
+ */
+void uapi_mqtt_main_stop(void);
+
+/**
+ * @brief 发送MQTT消息到队列
+ * @param topic 主题名称
+ * @param payload 消息内容
+ * @param payload_len 消息长度
+ * @param qos QoS等级
+ * @param retain 保留标志
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_send(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain);
+
+/**
+ * @brief 将接收到的MQTT消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param data 消息数据
+ * @param data_len 消息长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len);
+
+/**
+ * @brief 将订阅结果消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_subscribe_enqueue(const char *topic, uint8_t qos, int result);
+
+/**
+ * @brief 获取MQTT连接状态
+ * @return 连接状态(MQTT_STATE_DISCONNECTED/MQTT_STATE_CONNECTING/MQTT_STATE_CONNECTED)
+ */
+int uapi_mqtt_main_get_state(void);
+
+
+/**
+ * @brief 发布消息
+ */
+ int uapi_mqtt_publish(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UAPI_MQTT_H */
+
diff --git a/code/sdk/zhihui/MQTT/uapi_mqtt.c b/code/sdk/zhihui/MQTT/uapi_mqtt.c
new file mode 100644 (file)
index 0000000..512d96f
--- /dev/null
@@ -0,0 +1,688 @@
+#include "lwip/apps/mqtt.h"
+#include "lwip/ip_addr.h"
+#include "lwip/ip4_addr.h"
+#include "lwip/inet.h"
+#include "lwip/err.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "uapi_Mqtt_api.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+mqtt_log_level_t g_mqtt_log_level =0;
+
+/**
+ * @brief 设置MQTT日志等级
+ * @param level 日志等级(0=ERROR, 1=WARN, 2=INFO, 3=DEBUG)
+ */
+void mqtt_set_log_level(uint8_t level)
+{
+    if (level <= MQTT_LOG_DEBUG) {
+        g_mqtt_log_level = (mqtt_log_level_t)level;
+    }
+}
+
+// MQTT消息接收缓冲区最大大小(64KB)
+#define MQTT_RECV_BUFFER_MAX_SIZE (64 * 1024)
+
+// MQTT客户端实例
+static mqtt_client_t *g_mqtt_client = NULL;
+static bool g_mqtt_connected = false;
+
+// 回调函数
+static uapi_mqtt_connect_cb_t g_connect_cb = NULL;
+static uapi_mqtt_message_cb_t g_message_cb = NULL;
+static void *g_callback_arg = NULL;
+
+// 当前接收消息的主题(用于数据回调)
+static char g_current_topic[256] = {0};
+
+// 消息接收缓冲区(用于拼包)
+static uint8_t *g_recv_buffer = NULL;
+static uint32_t g_recv_total_len = 0;  // 消息总长度
+static uint32_t g_recv_current_len = 0;  // 当前接收长度
+
+// 当前连接的client_id(用于自动订阅)
+static char g_current_client_id[256] = {0};
+
+// 当前连接的publish_topic(用于发送连接成功消息)
+static char g_current_publish_topic[128] = {0};
+
+static void mqtt_request_cb(void *arg, err_t err);
+
+/**
+ * @brief 清理接收缓冲区
+ */
+static void mqtt_recv_buffer_cleanup(void)
+{
+    if (g_recv_buffer != NULL) {
+        free(g_recv_buffer);
+        g_recv_buffer = NULL;
+        g_recv_total_len = 0;
+        g_recv_current_len = 0;
+    }
+    g_current_topic[0] = '\0';
+}
+
+/**
+ * @brief 解析endpoint字符串,提取主机和端口
+ * @param endpoint 格式: "host:port" 或 "host"
+ * @param ipaddr 输出的IP地址
+ * @param port 输出的端口号(如果endpoint中没有端口,使用默认值)
+ * @return 0 成功,-1 失败
+ */
+static int parse_endpoint(const char *endpoint, ip_addr_t *ipaddr, uint16_t *port)
+{
+    if (!endpoint || !ipaddr || !port) {
+        return -1;
+    }
+
+    char host[256] = {0};
+    uint16_t default_port = MQTT_PORT; // 默认1883
+    
+    // 查找端口分隔符
+    const char *colon = strchr(endpoint, ':');
+    if (colon) {
+        // 有端口号
+        size_t host_len = colon - endpoint;
+        if (host_len >= sizeof(host)) {
+            host_len = sizeof(host) - 1;
+        }
+        strncpy(host, endpoint, host_len);
+        host[host_len] = '\0';
+        *port = (uint16_t)atoi(colon + 1);
+        if (*port == 0) {
+            *port = default_port;
+        }
+    } else {
+        // 无端口号,使用默认端口
+        strncpy(host, endpoint, sizeof(host) - 1);
+        host[sizeof(host) - 1] = '\0';
+        *port = default_port;
+    }
+
+    // 解析IP地址(ipaddr_aton会自动检测IPv4/IPv6)
+    if (ipaddr_aton(host, ipaddr) != 1) {
+        // 如果不是IP地址,尝试DNS解析(这里简化处理,实际应该使用DNS解析)
+        MQTT_WARN("Hostname resolution not implemented, using IP address only\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief MQTT连接状态回调
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
+{
+    (void)client;
+    (void)arg;
+    
+    if (status == MQTT_CONNECT_ACCEPTED) {
+        g_mqtt_connected = true;
+        // 连接成功后的自动订阅和通知由上层API处理
+    } else {
+        g_mqtt_connected = false;
+        // 连接断开时清理接收缓冲区
+        mqtt_recv_buffer_cleanup();
+    }
+    
+    // 调用用户回调(注意:用户回调应尽量快速返回,避免栈溢出)
+    if (g_connect_cb) {
+        g_connect_cb(g_callback_arg, (int)status);
+    }
+}
+
+/**
+ * @brief MQTT消息接收回调(主题)
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
+{
+    (void)arg;
+    
+    // 清理之前的缓冲区(如果存在)
+    if (g_recv_buffer != NULL) {
+        mqtt_recv_buffer_cleanup();
+    }
+    
+    // 保存当前主题(快速操作)
+    if (topic) {
+        strncpy(g_current_topic, topic, sizeof(g_current_topic) - 1);
+        g_current_topic[sizeof(g_current_topic) - 1] = '\0';
+    } else {
+        g_current_topic[0] = '\0';
+    }
+    
+    // 初始化接收缓冲区
+    if (tot_len > 0) {
+        // 限制最大消息大小
+        if (tot_len > MQTT_RECV_BUFFER_MAX_SIZE) {
+            g_recv_total_len = 0;
+            g_recv_current_len = 0;
+            return;
+        }
+        
+        // malloc 可能在回调上下文中执行,但这是必要的
+        g_recv_buffer = (uint8_t *)malloc(tot_len);
+        if (g_recv_buffer == NULL) {
+            g_recv_total_len = 0;
+            g_recv_current_len = 0;
+            return;
+        }
+        
+        g_recv_total_len = tot_len;
+        g_recv_current_len = 0;
+    } else {
+        g_recv_total_len = 0;
+        g_recv_current_len = 0;
+    }
+}
+
+/**
+ * @brief MQTT消息接收回调(数据)
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
+{
+    (void)arg;
+    
+    // 如果缓冲区未初始化,说明消息为空或初始化失败,直接返回
+    if (g_recv_buffer == NULL || g_recv_total_len == 0) {
+        if (flags & MQTT_DATA_FLAG_LAST) {
+            g_current_topic[0] = '\0';
+        }
+        return;
+    }
+    
+    // 检查是否会溢出
+    if (g_recv_current_len + len > g_recv_total_len) {
+        // 清理缓冲区
+        mqtt_recv_buffer_cleanup();
+        return;
+    }
+    
+    // 将数据片段复制到缓冲区(快速操作)
+    if (data && len > 0) {
+        memcpy(g_recv_buffer + g_recv_current_len, data, len);
+        g_recv_current_len += len;
+    }
+    
+    // 如果是最后一段数据,将完整的消息放入队列(由低优先级任务处理,避免在回调中执行耗时操作)
+    if (flags & MQTT_DATA_FLAG_LAST) {
+        // 验证接收长度是否匹配
+        if (g_recv_current_len != g_recv_total_len) {
+            // 长度不匹配,清理缓冲区
+            mqtt_recv_buffer_cleanup();
+            return;
+        }
+        
+        // 将消息放入队列,由低优先级任务处理(避免在回调中直接调用用户回调导致栈溢出)
+        if (g_current_topic[0] && g_recv_buffer && g_recv_current_len > 0) {
+            // 使用队列机制,将消息传递给主线程处理(函数内部会复制数据)
+            extern int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len);
+            uapi_mqtt_main_recv_enqueue(g_current_topic, g_recv_buffer, g_recv_current_len);
+            
+            // 清理本地缓冲区(队列已复制数据)
+            mqtt_recv_buffer_cleanup();
+        } else {
+            // 清理缓冲区和主题
+            mqtt_recv_buffer_cleanup();
+        }
+    }
+}
+
+/**
+ * @brief MQTT请求完成回调
+ */
+static void mqtt_request_cb(void *arg, err_t err)
+{
+    (void)arg;
+    if (err == ERR_OK) {
+        MQTT_DEBUG("Request completed successfully\n");
+    } else {
+        MQTT_ERROR("Request failed: %d\n", err);
+    }
+}
+
+
+/**
+ * @brief 初始化MQTT客户端
+ */
+int uapi_mqtt_init(void)
+{
+    if (g_mqtt_client != NULL) {
+        MQTT_INFO("Already initialized\n");
+        return 0;
+    }
+
+    g_mqtt_client = mqtt_client_new();
+    if (g_mqtt_client == NULL) {
+        MQTT_ERROR("Failed to create MQTT client\n");
+        return -1;
+    }
+
+    // 设置消息接收回调
+
+    MQTT_INFO("Initialized successfully\n");
+    return 0;
+}
+
+/**
+ * @brief 反初始化MQTT客户端
+ */
+void uapi_mqtt_deinit(void)
+{
+    if (g_mqtt_client) {
+        if (g_mqtt_connected) {
+            mqtt_disconnect(g_mqtt_client);
+            g_mqtt_connected = false;
+        }
+        mqtt_client_free(g_mqtt_client);
+        g_mqtt_client = NULL;
+    }
+    
+    g_connect_cb = NULL;
+    g_message_cb = NULL;
+    g_callback_arg = NULL;
+    g_current_client_id[0] = '\0';  // 清空client_id
+    g_current_publish_topic[0] = '\0';  // 清空publish_topic
+    
+    MQTT_INFO("Deinitialized\n");
+}
+
+/**
+ * @brief 从文件加载MQTT凭证
+ */
+int uapi_mqtt_load_credentials(mqtt_credentials_t *cred)
+{
+    if (!cred) {
+        return -1;
+    }
+
+    FILE *fp = fopen("/user/mqtt_credentials.json", "r");
+    if (!fp) {
+        MQTT_ERROR("Failed to open credentials file\n");
+        return -1;
+    }
+
+    // 读取文件内容
+    fseek(fp, 0, SEEK_END);
+    long file_size = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+
+    if (file_size <= 0 || file_size > 4096) {
+        fclose(fp);
+        return -1;
+    }
+
+    char *json_buf = (char *)malloc(file_size + 1);
+    if (!json_buf) {
+        fclose(fp);
+        return -1;
+    }
+
+    size_t read_len = fread(json_buf, 1, file_size, fp);
+    fclose(fp);
+    json_buf[read_len] = '\0';
+
+    // 解析JSON
+    cJSON *root = cJSON_Parse(json_buf);
+    free(json_buf);
+    
+    if (!root) {
+        MQTT_ERROR("Failed to parse credentials JSON\n");
+        return -1;
+    }
+
+    // 提取MQTT凭证
+    cJSON *mqtt_obj = cJSON_GetObjectItem(root, "mqtt");
+    if (!mqtt_obj || !cJSON_IsObject(mqtt_obj)) {
+        MQTT_ERROR("No 'mqtt' object found in JSON\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+
+    memset(cred, 0, sizeof(mqtt_credentials_t));
+
+    cJSON *item = cJSON_GetObjectItem(mqtt_obj, "endpoint");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->endpoint, item->valuestring, sizeof(cred->endpoint) - 1);
+    }
+
+    item = cJSON_GetObjectItem(mqtt_obj, "client_id");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->client_id, item->valuestring, sizeof(cred->client_id) - 1);
+    }
+
+    item = cJSON_GetObjectItem(mqtt_obj, "username");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->username, item->valuestring, sizeof(cred->username) - 1);
+    }
+
+    item = cJSON_GetObjectItem(mqtt_obj, "password");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->password, item->valuestring, sizeof(cred->password) - 1);
+    }
+
+    item = cJSON_GetObjectItem(mqtt_obj, "publish_topic");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->publish_topic, item->valuestring, sizeof(cred->publish_topic) - 1);
+    }
+
+    item = cJSON_GetObjectItem(mqtt_obj, "subscribe_topic");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(cred->subscribe_topic, item->valuestring, sizeof(cred->subscribe_topic) - 1);
+    }
+
+    cJSON_Delete(root);
+
+    MQTT_INFO("Credentials loaded: endpoint=%s, client_id=%s\n", 
+              cred->endpoint, cred->client_id);
+    return 0;
+}
+
+/**
+ * @brief 连接MQTT服务器
+ */
+int uapi_mqtt_connect(const mqtt_credentials_t *cred, 
+                      uapi_mqtt_connect_cb_t connect_cb,
+                      uapi_mqtt_message_cb_t message_cb,
+                      void *arg)
+{
+    if (!g_mqtt_client) {
+        if (uapi_mqtt_init() != 0) {
+            return -1;
+        }
+    }
+
+    mqtt_credentials_t credentials = {0};
+    const mqtt_credentials_t *use_cred = cred;
+
+    // 如果没有提供凭证,从文件加载
+    if (!use_cred) {
+        if (uapi_mqtt_load_credentials(&credentials) != 0) {
+            MQTT_ERROR("Failed to load credentials\n");
+            return -1;
+        }
+        use_cred = &credentials;
+    }
+
+    // 检查必要的字段
+    if (!use_cred->endpoint[0] || !use_cred->client_id[0]) {
+        MQTT_ERROR("Missing required credentials (endpoint or client_id)\n");
+        return -1;
+    }
+
+    // 保存client_id用于自动订阅
+    strncpy(g_current_client_id, use_cred->client_id, sizeof(g_current_client_id) - 1);
+    g_current_client_id[sizeof(g_current_client_id) - 1] = '\0';
+    
+    // 保存publish_topic用于发送连接通知
+    if (use_cred->publish_topic[0] != '\0') {
+        strncpy(g_current_publish_topic, use_cred->publish_topic, sizeof(g_current_publish_topic) - 1);
+        g_current_publish_topic[sizeof(g_current_publish_topic) - 1] = '\0';
+    } else {
+        g_current_publish_topic[0] = '\0';  // 使用默认主题
+    }
+
+    // 保存回调函数
+    g_connect_cb = connect_cb;
+    g_message_cb = message_cb;
+    g_callback_arg = arg;
+
+    // 解析endpoint
+    ip_addr_t ipaddr;
+    uint16_t port;
+    if (parse_endpoint(use_cred->endpoint, &ipaddr, &port) != 0) {
+        MQTT_ERROR("Failed to parse endpoint: %s\n", use_cred->endpoint);
+        return -1;
+    }
+
+    // 准备连接信息
+    struct mqtt_connect_client_info_t ci = {0};
+    ci.client_id = use_cred->client_id;
+    ci.client_user = use_cred->username[0] ? use_cred->username : NULL;
+    ci.client_pass = use_cred->password[0] ? use_cred->password : NULL;
+    ci.keep_alive = 60*10; // 60秒保活
+    ci.will_topic = NULL;
+    ci.will_msg = NULL;
+    ci.will_qos = 0;
+    ci.will_retain = 0;
+
+    MQTT_INFO("Connecting to %s:%d, client_id=%s\n", 
+              use_cred->endpoint, port, use_cred->client_id);
+
+    // 连接MQTT服务器
+    err_t err = mqtt_client_connect(g_mqtt_client, &ipaddr, port, 
+                                     mqtt_connection_cb, NULL, &ci);
+    if (err != ERR_OK) {
+        MQTT_ERROR("Failed to initiate connection: %d\n", err);
+        return -1;
+    }
+
+    mqtt_set_inpub_callback(g_mqtt_client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, NULL);
+
+
+    return 0;
+}
+
+/**
+ * @brief 断开MQTT连接
+ */
+int uapi_mqtt_disconnect(void)
+{
+    if (!g_mqtt_client) {
+        return -1;
+    }
+
+    if (g_mqtt_connected) {
+        mqtt_disconnect(g_mqtt_client);
+        g_mqtt_connected = false;
+        MQTT_INFO("Disconnected\n");
+    }
+    
+    // 清理接收缓冲区
+    mqtt_recv_buffer_cleanup();
+
+    return 0;
+}
+
+/**
+ * @brief 检查MQTT连接状态
+ */
+bool uapi_mqtt_is_connected(void)
+{
+    if (!g_mqtt_client) {
+        return false;
+    }
+    return g_mqtt_connected && mqtt_client_is_connected(g_mqtt_client);
+}
+
+/**
+ * @brief 获取MQTT客户端实例(内部使用,供上层API调用)
+ * @return mqtt_client_t* 客户端实例,NULL表示未初始化
+ */
+mqtt_client_t *uapi_mqtt_get_client(void)
+{
+    return g_mqtt_client;
+}
+
+/**
+ * @brief 获取当前连接的client_id(内部使用,供上层API调用)
+ * @param client_id 输出的client_id缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_get_client_id(char *client_id, size_t len)
+{
+    if (!client_id || len == 0) {
+        return -1;
+    }
+    
+    if (g_current_client_id[0] == '\0') {
+        return -1;
+    }
+    
+    strncpy(client_id, g_current_client_id, len - 1);
+    client_id[len - 1] = '\0';
+    return 0;
+}
+
+/**
+ * @brief 获取当前连接的publish_topic(内部使用,供上层API调用)
+ * @param publish_topic 输出的publish_topic缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败(如果未设置,返回-1但不表示错误)
+ */
+int uapi_mqtt_get_publish_topic(char *publish_topic, size_t len)
+{
+    if (!publish_topic || len == 0) {
+        return -1;
+    }
+    
+    if (g_current_publish_topic[0] == '\0') {
+        return -1;  // 未设置,但不一定是错误
+    }
+    
+    strncpy(publish_topic, g_current_publish_topic, len - 1);
+    publish_topic[len - 1] = '\0';
+    return 0;
+}
+
+
+
+
+/* 订阅信息结构体(用于传递给回调) */
+typedef struct {
+    char topic[256];
+    uint8_t qos;
+} subscribe_info_t;
+
+/**
+ * @brief MQTT请求完成回调
+ */
+static void mqtt_request_subscribe_cb(void *arg, err_t err)
+{
+    subscribe_info_t *info = (subscribe_info_t *)arg;
+    
+    if (info == NULL) {
+        MQTT_ERROR("mqtt_request_subscribe_cb: invalid arg\n");
+        return;
+    }
+    
+    int result = (err == ERR_OK) ? 0 : -1;
+    
+    if (err == ERR_OK) {
+        MQTT_DEBUG("mqtt_request_subscribe_cb Request completed successfully for topic: %s\n", info->topic);
+    } else {
+        MQTT_ERROR("Request failed for topic: %s, error: %d\n", info->topic, err);
+    }
+    
+    // 将订阅结果放入接收队列,由主线程处理并触发用户回调
+    uapi_mqtt_main_subscribe_enqueue(info->topic, info->qos, result);
+    
+    // 释放分配的内存
+    free(info);
+}
+
+
+
+/**
+ * @brief 订阅主题
+ */
+int uapi_mqtt_subscribe(const char *topic, uint8_t qos)
+{
+    if (!g_mqtt_client || !topic) {
+        return -1;
+    }
+
+    if (!uapi_mqtt_is_connected()) {
+        MQTT_WARN("Not connected, cannot subscribe\n");
+        return -1;
+    }
+
+    if (qos > 2) {
+        qos = 1; // 默认QoS 1
+    }
+
+    MQTT_INFO("Subscribing to topic: %s, QoS: %d\n", topic, qos);
+
+    // 分配订阅信息结构体,传递给回调函数
+    subscribe_info_t *info = (subscribe_info_t *)malloc(sizeof(subscribe_info_t));
+    if (info == NULL) {
+        MQTT_ERROR("Failed to allocate subscribe info\n");
+        return -1;
+    }
+    
+    strncpy(info->topic, topic, sizeof(info->topic) - 1);
+    info->topic[sizeof(info->topic) - 1] = '\0';
+    info->qos = qos;
+
+    err_t err = mqtt_subscribe(g_mqtt_client, topic, qos, mqtt_request_subscribe_cb, info);
+    if (err != ERR_OK) {
+        MQTT_ERROR("Failed to subscribe: %d\n", err);
+        free(info);  // 订阅失败时释放内存
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief 取消订阅主题
+ */
+int uapi_mqtt_unsubscribe(const char *topic)
+{
+    if (!g_mqtt_client || !topic) {
+        return -1;
+    }
+
+    if (!uapi_mqtt_is_connected()) {
+        MQTT_WARN("Not connected, cannot unsubscribe\n");
+        return -1;
+    }
+
+    MQTT_INFO("Unsubscribing from topic: %s\n", topic);
+
+    err_t err = mqtt_unsubscribe(g_mqtt_client, topic, mqtt_request_cb, NULL);
+    if (err != ERR_OK) {
+        MQTT_ERROR("Failed to unsubscribe: %d\n", err);
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief 发布消息
+ */
+int uapi_mqtt_publish(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain)
+{
+    if (!g_mqtt_client || !topic || !payload) {
+        return -1;
+    }
+
+    if (!uapi_mqtt_is_connected()) {
+        MQTT_WARN("Not connected, cannot publish\n");
+        return -1;
+    }
+
+    if (qos > 2) {
+        qos = 0; // 默认QoS 0
+    }
+
+    MQTT_DEBUG("Publishing to topic: %s, len: %d, QoS: %d\n", topic, payload_len, qos);
+
+    err_t err = mqtt_publish(g_mqtt_client, topic, payload, payload_len, qos, retain, 
+                             mqtt_request_cb, NULL);
+    if (err != ERR_OK) {
+        MQTT_ERROR("Failed to publish: %d\n", err);
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/code/sdk/zhihui/MQTT/uapi_mqtt_at.c b/code/sdk/zhihui/MQTT/uapi_mqtt_at.c
new file mode 100644 (file)
index 0000000..e7b3a3b
--- /dev/null
@@ -0,0 +1,232 @@
+#include "at_cmd_api.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "errcode.h"
+#include "uapi_Mqtt_api.h"
+#include "audio_capture_wrapper.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+extern mqtt_log_level_t g_mqtt_log_level ;
+
+
+// 前向声明ln_OTA.c中的函数(ln_OTA.c仍在原位置)
+extern int ln_ota_send_device_info_json(const char *url, void *credentials);
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define UAPI_MQTT_MAX_ARGC 8
+#define UAPI_MQTT_MAX_ARGV_LEN 256
+
+
+/**
+ * @brief 解析AT命令参数
+ */
+static int uapi_mqtt_parse_params(uint8_t *para, uint32_t paraLen, 
+                                 uint8_t argv[UAPI_MQTT_MAX_ARGC][UAPI_MQTT_MAX_ARGV_LEN], 
+                                 uint32_t *argc)
+{
+    uint32_t pos = 0;
+    *argc = 0;
+
+    for (uint32_t i = 0; i < paraLen; i++) {
+        if ((para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') && pos != 0) {
+            argv[*argc][pos] = '\0';
+            *argc += 1;
+            pos = 0;
+            if (*argc >= UAPI_MQTT_MAX_ARGC) {
+                return -1;
+            }
+        } else {
+            if (para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') {
+                continue;
+            }
+            argv[*argc][pos] = para[i];
+            pos++;
+            if (pos >= UAPI_MQTT_MAX_ARGV_LEN) {
+                return -1;
+            }
+        }
+    }
+    if (pos != 0) {
+        argv[*argc][pos] = '\0';
+        *argc += 1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief MQTT连接状态回调(用于AT命令测试)
+ */
+static void mqtt_at_connect_cb(void *arg, int status)
+{
+    (void)arg;
+    MQTT_INFO("Connection status changed: %d\n", status);
+}
+
+/**
+ * @brief MQTT消息接收回调(用于AT命令测试)
+ */
+static void mqtt_at_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+    (void)arg;
+    MQTT_INFO("Received message - Topic: %s, Length: %d\n", topic, len);
+    if (data && len > 0) {
+        MQTT_DEBUG("Message content: ");
+        for (uint16_t i = 0; i < len && i < 100; i++) {  // 限制打印长度
+            printf("%c", (data[i] >= 32 && data[i] < 127) ? data[i] : '.');
+        }
+        printf("\n");
+    }
+}
+
+/* OTA-发送设备信息到服务器:AT^LN_OTA_SEND_DEVICE_INFO */
+// static uint32_t ln_ota_send_device_info_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+// {
+//     (void)para;
+//     (void)paraLen;
+//     (void)strCommonCmd;
+    
+//     printf("[LN][OTA_SEND_DEVICE_INFO]\n");
+    
+//     // 直接调用封装函数,使用默认URL(NULL表示使用默认URL)
+//     int ret = ln_ota_send_device_info_json(NULL, NULL);
+//     if (ret == 0) {
+//         printf("+LN_OTA_SEND_DEVICE_INFO: OK\n");
+//         return ERRCODE_SUCC;
+//     } else {
+//         printf("+LN_OTA_SEND_DEVICE_INFO: FAIL\n");
+//         return ERRCODE_FAIL;
+//     }
+// }
+
+/* MQTT-初始化:AT^LN_MQTT_INIT */
+static uint32_t uapi_mqtt_init_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)para;
+    (void)paraLen;
+    (void)strCommonCmd;
+    
+    printf("[UAPI_MQTT][MQTT_INIT]\n");
+    
+    int ret = uapi_mqtt_init();
+    if (ret == 0) {
+        printf("+LN_MQTT_INIT: OK\n");
+        return ERRCODE_SUCC;
+    } else {
+        printf("+LN_MQTT_INIT: FAIL\n");
+        return ERRCODE_FAIL;
+    }
+}
+
+/* MQTT-反初始化:AT^LN_MQTT_DEINIT */
+static uint32_t uapi_mqtt_deinit_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)para;
+    (void)paraLen;
+    (void)strCommonCmd;
+    
+    printf("[UAPI_MQTT][MQTT_DEINIT]\n");
+    
+    uapi_mqtt_deinit();
+    printf("+LN_MQTT_DEINIT: OK\n");
+    return ERRCODE_SUCC;
+}
+
+/* MQTT-连接:AT^LN_MQTT_CONNECT */
+static uint32_t uapi_mqtt_connect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)strCommonCmd;
+    
+    printf("[UAPI_MQTT][MQTT_CONNECT]\n");
+    
+    // 从文件加载凭证并连接(不使用参数)
+    int ret = uapi_mqtt_connect(NULL, mqtt_at_connect_cb, mqtt_at_message_cb, NULL);
+    if (ret == 0) {
+        printf("+LN_MQTT_CONNECT: OK\n");
+        return ERRCODE_SUCC;
+    } else {
+        printf("+LN_MQTT_CONNECT: FAIL\n");
+        return ERRCODE_FAIL;
+    }
+}
+
+/* MQTT-断开连接:AT^LN_MQTT_DISCONNECT */
+static uint32_t uapi_mqtt_disconnect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)para;
+    (void)paraLen;
+    (void)strCommonCmd;
+    
+    printf("[UAPI_MQTT][MQTT_DISCONNECT]\n");
+    
+    int ret = uapi_mqtt_disconnect();
+    if (ret == 0) {
+        printf("+LN_MQTT_DISCONNECT: OK\n");
+        return ERRCODE_SUCC;
+    } else {
+        printf("+LN_MQTT_DISCONNECT: FAIL\n");
+        return ERRCODE_FAIL;
+    }
+}
+
+/* MQTT-查询连接状态:AT^LN_MQTT_IS_CONNECTED? */
+static uint32_t uapi_mqtt_is_connected_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)para;
+    (void)paraLen;
+    (void)strCommonCmd;
+    
+    printf("[UAPI_MQTT][MQTT_IS_CONNECTED]\n");
+    
+    bool connected = uapi_mqtt_is_connected();
+    if (connected) {
+        printf("+LN_MQTT_IS_CONNECTED: 1\n");
+    } else {
+        printf("+LN_MQTT_IS_CONNECTED: 0\n");
+    }
+    return ERRCODE_SUCC;
+}
+
+
+static uint32_t uapi_mqtt_AudioCaptureSample_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    (void)para;
+    (void)paraLen;
+    (void)strCommonCmd;
+    
+    const char *defaultArgs[6] = {"01", "opus", "16000", "1", "16", "user/userdata/test.ogg"};
+
+    int ret = AudioCaptureSample(6, defaultArgs);
+    LOS_Msleep(1000*10);
+
+    int32_t argc = 1;
+    uint8_t *argv = (uint8_t*)"stop";
+    AudioCaptureSample(argc, (const char **)&argv);
+
+    return ERRCODE_SUCC;
+}
+
+
+
+/* 命令表 */
+static const at_cmd_table_t g_uapi_mqtt_at_cmd[] = {
+    // {(char *)"AT^LN_OTA_SEND_DEVICE_INFO", ln_ota_send_device_info_at, (char *)"发送设备信息到OTA服务器: AT^LN_OTA_SEND_DEVICE_INFO"},
+    {(char *)"AT^LN_MQTT_INIT", uapi_mqtt_init_at, (char *)"初始化MQTT客户端: AT^LN_MQTT_INIT"},
+    {(char *)"AT^LN_MQTT_DEINIT", uapi_mqtt_deinit_at, (char *)"反初始化MQTT客户端: AT^LN_MQTT_DEINIT"},
+    {(char *)"AT^LN_MQTT_CONNECT", uapi_mqtt_connect_at, (char *)"连接MQTT服务器: AT^LN_MQTT_CONNECT"},
+    {(char *)"AT^LN_MQTT_DISCONNECT", uapi_mqtt_disconnect_at, (char *)"断开MQTT连接: AT^LN_MQTT_DISCONNECT"},
+    {(char *)"AT^LN_MQTT_IS_CONNECTED?", uapi_mqtt_is_connected_at, (char *)"查询MQTT连接状态: AT^LN_MQTT_IS_CONNECTED?"},
+    {(char *)"AT^LN_MQTT_CAPTURE?", uapi_mqtt_AudioCaptureSample_at, (char *)"录音测试"},
+
+};
+
+at_cmd_table_t *get_uapi_mqtt_at_cmd_table(uint32_t *cmd_count)
+{
+    if (cmd_count) {
+        *cmd_count = ARRAY_COUNT(g_uapi_mqtt_at_cmd);
+    }
+    return (at_cmd_table_t *)g_uapi_mqtt_at_cmd;
+}
+
diff --git a/code/sdk/zhihui/MQTT/uapi_mqtt_at.h b/code/sdk/zhihui/MQTT/uapi_mqtt_at.h
new file mode 100644 (file)
index 0000000..d699d4f
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef UAPI_MQTT_AT_H
+#define UAPI_MQTT_AT_H
+
+#include <stdint.h>
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* MQTT AT 指令表导出 */
+at_cmd_table_t *get_uapi_mqtt_at_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UAPI_MQTT_AT_H */
+
+
+
index 878be8c..7b442a0 100644 (file)
@@ -19,11 +19,18 @@ ${ROOT_DIR}/middleware/services/media/foundation/utils/include
 ${ROOT_DIR}/include
 ${ROOT_DIR}/open_source/libogg/libogg-1.3.5/include/ogg
 ${ROOT_DIR}/open_source/libogg/libogg-1.3.5/include
+${ROOT_DIR}/middleware/services/media/foundation/player/interfaces/kits
+${ROOT_DIR}/middleware/services/gui/uikit/surface/interfaces/kits
+${ROOT_DIR}/open_source/openharmony/drivers/peripheral/display/interfaces/include
+${ROOT_DIR}middleware/services/media/foundation/audio_capturer/interfaces/kits
+${ROOT_DIR}/open_source/openharmony/foundation/multimedia/audio_capturer/interfaces/kits
 )
 
 set(AI_SOURCES
 ${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service_ext.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service_mqtt.cpp
+
 
 )
 
index 020e747..9937850 100644 (file)
@@ -1433,7 +1433,7 @@ static void AIVoiceInputThreadFunc(void *data)
         } 
       
         LOS_Msleep(10);
-        }
+    }
 
 
     MEDIA_INFO_LOG("AI voice input thread stopped");
@@ -2183,24 +2183,46 @@ int32_t AI_WriteAudioData(const uint8_t* data, uint32_t size)
     // 写入音频数据到输出流
     int32_t ret = AudioStreamOutStreamWrite(data, size);
     
-    // 根据比特率动态计算延迟时间
-    // 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
-    // 当比特率更高时,延迟时间更短
-    // 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
-    uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
-    printf("delay_us %d\r\n",delay_us);
-    
-    // 确保延迟时间在合理范围内(最小10微秒)
-    if (delay_us < 20) {
-        delay_us = 20;
+    if(g_aiVoiceContext->outputAudioFormat==MP3)
+    {
+        // 根据比特率动态计算延迟时间
+        // 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
+        // 当比特率更高时,延迟时间更短
+        // 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
+        uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+        printf("delay_us %d\r\n",delay_us);
+        
+        // 确保延迟时间在合理范围内(最小10微秒)
+        if (delay_us < 20) {
+            delay_us = 20;
+        }
+        usleep(delay_us-20);
+        if (ret != 0) {
+            retry_count++;
+            // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+            usleep(delay_us*retry_count/10*5);
+            goto AI_WRITE;
+        }
     }
-    usleep(delay_us-20);
-    if (ret != 0) {
-        retry_count++;
-        // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
-        usleep(delay_us*retry_count/10*5);
-        goto AI_WRITE;
+    else if(g_aiVoiceContext->outputAudioFormat==PCM)
+    {
+         uint32_t delay_us = size*20;
+        printf("delay_us %d\r\n",delay_us);
+        
+        // 确保延迟时间在合理范围内(最小10微秒)
+        if (delay_us < 20) {
+            delay_us = 20;
+        }
+        usleep(delay_us-20);
+        if (ret != 0) {
+            retry_count++;
+            // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+            usleep(delay_us*retry_count/10*5);
+            goto AI_WRITE;
+        }
+
     }
+  
     
     // 调用注册的回调函数
     if (g_writeAudioDataCallback != nullptr && size!=SILENCE_AUDIO_SIZE) {
diff --git a/code/sdk/zhihui/ai/media/ai_media_service_mqtt.cpp b/code/sdk/zhihui/ai/media/ai_media_service_mqtt.cpp
new file mode 100644 (file)
index 0000000..a256a30
--- /dev/null
@@ -0,0 +1,1401 @@
+/*
+ * Copyright (c) CompanyNameMagicTag. 2023-2023. All rights reserved.
+ * Description: AI media service for MQTT recording
+ * Author: Media Software Group
+ * Create: 2023-07-06
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <string>
+#include <memory>
+#include <time.h>
+#include "securec.h"
+#include "audio_manager.h"
+#include "audio_capturer.h"
+#include "audio_base_type.h"
+
+// 宏定义:选择使用 AudioStreamInInit 还是 AudioCapturer
+// 定义 USE_AUDIO_STREAM_IN 则使用 AudioStreamInInit,否则使用 AudioCapturer
+#ifndef USE_AUDIO_STREAM_IN
+#define USE_AUDIO_STREAM_IN 1
+#endif
+
+#if USE_AUDIO_STREAM_IN
+#include "audio_stream_in.h"
+#endif
+#include "media_log.h"
+#include "media_errors.h"
+#include "media_thread_adapt.h"
+#include "audio_manager_c_wrapper.h"
+#include "thread_init.h"
+#include "errcode.h"
+#include "ai_media.h"
+#include "cmsis_os2.h"
+#include "player.h"
+#include "audio_player_service.h"
+#include "ogg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+using namespace OHOS::Media;
+using namespace OHOS::Audio;
+using namespace Audio;
+using OHOS::Media::Player;
+using OHOS::AudioPlayerServiceCallback;
+using OHOS::AudioPlayerService;
+using Audio::InterruptListener;
+using Audio::AudioInterrupt;
+using Audio::AudioManager;
+
+// 录音缓冲区大小
+const uint32_t MQTT_RECORD_BUFFER_SIZE = 0x800;  // 2KB
+
+// 录音数据回调函数类型
+typedef void (*MqttRecordDataCallback)(const uint8_t* data, uint32_t size, void* userData);
+
+// 录音参数结构体
+typedef struct {
+    int32_t audioFormat;      // 音频格式
+    uint32_t channelCount;    // 声道数
+    uint32_t sampleRate;      // 采样率
+} MqttRecordAudioParams;
+
+// OGG 封装上下文结构体(参考 audio_capture_wrapper.cpp)
+typedef struct MqttOggContext {
+    ogg_stream_state oggStream;
+    int64_t sampleRate;
+    int64_t channels;
+    int64_t granulepos;
+    int64_t packetCount;
+    int32_t serialno;
+    bool isEnd;
+    ogg_page *page;
+    ogg_packet *packet;
+    unsigned char *idHeader;
+    unsigned char *commentHeader;
+    bool initialized;  // OGG 上下文是否已初始化
+} MqttOggContext;
+
+// 录音上下文结构体
+typedef struct {
+    AudioSession sessionId;
+    bool isRecordStopped;
+    MediaThreadCondHandle cond;
+    MediaThreadIdHandle taskHandle;
+    char threadName[32];
+    uint8_t *dataBuffer;
+    uint32_t bufferSize;
+    MqttRecordDataCallback dataCallback;
+    void* callbackUserData;
+    AudioCodecFormat audioFormat;
+    uint32_t channelCount;
+    uint32_t sampleRate;
+#if USE_AUDIO_STREAM_IN
+    // 使用 AudioStreamIn 接口
+    bool streamInInitialized;  // AudioStreamIn 是否已初始化
+#else
+    // 使用 AudioCapturer 接口
+    std::shared_ptr<OHOS::Audio::AudioCapturer> audioCapturer;
+    size_t framesize;  // 帧大小(用于 Read 接口)
+#endif
+    FILE *debugFile;   // 调试文件句柄(用于保存录音数据)
+} MqttRecordContext;
+
+// 全局变量
+static MediaMutexHandle g_mqttRecordMutex = nullptr;
+static MqttRecordContext *g_mqttRecordContext = nullptr;
+static volatile bool g_mqttRecordThreadStopped = false;  // 线程停止标志
+
+// 默认音频参数
+static const AudioCodecFormat MQTT_DEFAULT_AUDIO_FORMAT = SBC;
+static const uint32_t MQTT_DEFAULT_CHANNEL_COUNT = 1;
+static const uint32_t MQTT_DEFAULT_SAMPLE_RATE = 16000;
+
+// OGG 封装相关常量(参考 audio_capture_wrapper.cpp)
+const uint32_t MQTT_OGG_HEADER_STRLEN = 8;
+const uint32_t MQTT_OGG_OPUS_DELAY_TIME_DIVISOR = 0;
+const uint32_t MQTT_OGG_OPUS_DELAY_TIME_DIVIDED = 100;
+const uint32_t MQTT_OGG_OPUS_ID_HEADER_LEN = 19;
+const uint32_t MQTT_OGG_OPUS_COMMENT_HEADER_LEN = 25;
+const uint32_t MQTT_OGG_OPUS_ENCODE_HEADER_SIZE = 8;
+const uint32_t MQTT_OGG_OPUS_OPUSTAGS_LEN = 12;
+const uint32_t MQTT_OGG_OPUS_SAMPLERATE = 16000;
+const uint32_t MQTT_OGG_MILLSECOND_TO_SECOND = 6000;
+
+/**
+ * @brief 分配内存并清零(用于 OGG 封装)
+ */
+static void* MqttOggMemCalloc(size_t bytesNum)
+{
+    void *tmp = malloc(bytesNum);
+    if (tmp == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: malloc failed!");
+        return nullptr;
+    }
+    if (memset_s(tmp, bytesNum, 0, bytesNum) != EOK) {
+        MEDIA_ERR_LOG("MQTT OGG: memset_s failed!");
+        free(tmp);
+        return nullptr;
+    }
+    return tmp;
+}
+
+/**
+ * @brief 释放内存(用于 OGG 封装)
+ */
+static void MqttOggMemFree(void **ptr)
+{
+    if (ptr == nullptr || *ptr == nullptr) {
+        return;
+    }
+    free(*ptr);
+    *ptr = nullptr;
+}
+
+/**
+ * @brief 初始化 OGG 头部(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggHeaderInit(MqttOggContext *oggCtx, uint32_t sampleRate, uint32_t channelCount)
+{
+    if (oggCtx == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context");
+        return -1;
+    }
+
+    // 分配并初始化 ID Header
+    oggCtx->idHeader = static_cast<unsigned char*>(MqttOggMemCalloc(MQTT_OGG_OPUS_ID_HEADER_LEN));
+    if (oggCtx->idHeader == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Failed to allocate idHeader");
+        return -1;
+    }
+    
+    if (memcpy_s(oggCtx->idHeader, MQTT_OGG_HEADER_STRLEN, "OpusHead", MQTT_OGG_HEADER_STRLEN) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: memcpy failed!");
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        return -1;
+    }
+    
+    oggCtx->idHeader[0x8] = 0x01;
+    oggCtx->idHeader[0x9] = channelCount;
+    uint32_t preSkip = sampleRate * MQTT_OGG_OPUS_DELAY_TIME_DIVISOR / MQTT_OGG_OPUS_DELAY_TIME_DIVIDED;
+    oggCtx->idHeader[0xA] = preSkip & 0xFF;
+    oggCtx->idHeader[0xB] = (preSkip >> 0x8);
+    oggCtx->idHeader[0xC] = sampleRate & 0xFF;
+    oggCtx->idHeader[0xD] = (sampleRate >> 0x8) & 0xFF;
+    oggCtx->idHeader[0xE] = (sampleRate >> 0x10) & 0xFF;
+    oggCtx->idHeader[0xF] = (sampleRate >> 0x18) & 0xFF;
+
+    // 分配并初始化 Comment Header
+    oggCtx->commentHeader = static_cast<unsigned char*>(MqttOggMemCalloc(MQTT_OGG_OPUS_COMMENT_HEADER_LEN));
+    if (oggCtx->commentHeader == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Failed to allocate commentHeader");
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        return -1;
+    }
+    
+    if (memcpy_s(oggCtx->commentHeader, MQTT_OGG_HEADER_STRLEN, "OpusTags", MQTT_OGG_HEADER_STRLEN) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: Opus commentHeader memcpy failed!");
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        MqttOggMemFree((void **)&oggCtx->commentHeader);
+        return -1;
+    }
+    
+    const char *vendor = "libogg-1.3.5";
+    uint32_t vendorLen = strlen(vendor);
+    oggCtx->commentHeader[0x8] = vendorLen & 0xFF;
+    oggCtx->commentHeader[0x9] = (vendorLen >> 0x8) & 0xFF;
+    oggCtx->commentHeader[0xA] = (vendorLen >> 0x10) & 0xFF;
+    oggCtx->commentHeader[0xB] = (vendorLen >> 0x18) & 0xFF;
+
+    if (memcpy_s(oggCtx->commentHeader + MQTT_OGG_OPUS_OPUSTAGS_LEN, vendorLen, vendor, vendorLen) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: Opus commentHeader vendor memcpy failed!");
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        MqttOggMemFree((void **)&oggCtx->commentHeader);
+        return -1;
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 刷新 OGG 流到文件(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggStreamFlush(MqttOggContext *oggCtx, FILE *pfd)
+{
+    if (oggCtx == nullptr || pfd == nullptr || oggCtx->page == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for flush");
+        return -1;
+    }
+    
+    while (ogg_stream_flush(&oggCtx->oggStream, oggCtx->page)) {
+        int32_t ret = fwrite(oggCtx->page->header, 1, oggCtx->page->header_len, pfd);
+        if (ret != (int32_t)oggCtx->page->header_len) {
+            MEDIA_ERR_LOG("MQTT OGG: Failed to write page header: errno=%d, errmsg=%s", errno, strerror(errno));
+            return -1;
+        }
+        ret = fwrite(oggCtx->page->body, 1, oggCtx->page->body_len, pfd);
+        if (ret != (int32_t)oggCtx->page->body_len) {
+            MEDIA_ERR_LOG("MQTT OGG: Failed to write page body: errno=%d, errmsg=%s", errno, strerror(errno));
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief 写入 OGG 页面到文件(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggWritePage(MqttOggContext *oggCtx, FILE *pfd)
+{
+    if (oggCtx == nullptr || pfd == nullptr || oggCtx->page == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for write page");
+        return -1;
+    }
+    
+    if (ogg_stream_pageout(&oggCtx->oggStream, oggCtx->page)) {
+        int32_t ret = fwrite(oggCtx->page->header, 1, oggCtx->page->header_len, pfd);
+        if (ret != (int32_t)oggCtx->page->header_len) {
+            MEDIA_ERR_LOG("MQTT OGG: Failed to write page header: errno=%d, errmsg=%s", errno, strerror(errno));
+            return -1;
+        }
+        ret = fwrite(oggCtx->page->body, 1, oggCtx->page->body_len, pfd);
+        if (ret != (int32_t)oggCtx->page->body_len) {
+            MEDIA_ERR_LOG("MQTT OGG: Failed to write page body: errno=%d, errmsg=%s", errno, strerror(errno));
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief 获取全局互斥锁
+ */
+static MediaMutexHandle GetMqttRecordMutex(void)
+{
+    if (g_mqttRecordMutex == nullptr) {
+        static bool init_once = false;
+        if (!init_once) {
+            init_once = true;
+            g_mqttRecordMutex = MediaMutexCreate(nullptr);
+            if (g_mqttRecordMutex != nullptr) {
+                MEDIA_INFO_LOG("MQTT record mutex created successfully");
+            } else {
+                MEDIA_ERR_LOG("Failed to create MQTT record mutex");
+            }
+        }
+    }
+    return g_mqttRecordMutex;
+}
+
+/**
+ * @brief 初始化录音资源
+ */
+static bool InitMqttRecordResources(MqttRecordContext *context)
+{
+    context->cond = MediaThreadCondCreate();
+    if (context->cond == nullptr) {
+        MEDIA_ERR_LOG("Failed to create MQTT record thread cond");
+        return false;
+    }
+
+    context->dataBuffer = (uint8_t*)malloc(MQTT_RECORD_BUFFER_SIZE);
+    if (context->dataBuffer == nullptr) {
+        MEDIA_ERR_LOG("Failed to allocate MQTT record buffer");
+        MediaThreadCondDestroy(&context->cond);
+        return false;
+    }
+
+    context->bufferSize = MQTT_RECORD_BUFFER_SIZE;
+    
+    // 打开调试文件用于保存录音数据(方便验证数据正确性)
+    time_t now = time(nullptr);
+    struct tm *tm_info = localtime(&now);
+    char filename[128];
+    snprintf(filename, sizeof(filename), "/user/mqtt_record_%04d%02d%02d_%02d%02d%02d.sbc",
+             tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+             tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
+    
+    context->debugFile = fopen(filename, "wb");
+    if (context->debugFile == nullptr) {
+        MEDIA_ERR_LOG("Failed to open debug file: %s", filename);
+        // 文件打开失败不影响录音功能,继续执行
+    } else {
+        MEDIA_INFO_LOG("MQTT record debug file opened: %s", filename);
+    }
+    
+    return true;
+}
+
+/**
+ * @brief 清理录音资源
+ */
+static void DeinitMqttRecordResources(MqttRecordContext *context)
+{
+    if (context != nullptr) {
+#if USE_AUDIO_STREAM_IN
+        // 使用 AudioStreamIn 接口
+        if (context->streamInInitialized) {
+            AudioStreamInStop();
+            AudioStreamInDeinit();
+            context->streamInInitialized = false;
+        }
+#else
+        // 使用 AudioCapturer 接口
+        if (context->audioCapturer != nullptr) {
+            context->audioCapturer->Stop();
+            context->audioCapturer->Release();
+            context->audioCapturer.reset();
+            context->audioCapturer = nullptr;
+        }
+#endif
+
+        // 关闭调试文件
+        if (context->debugFile != nullptr) {
+            fclose(context->debugFile);
+            context->debugFile = nullptr;
+            MEDIA_INFO_LOG("MQTT record debug file closed");
+        }
+
+        if (context->dataBuffer != nullptr) {
+            free(context->dataBuffer);
+            context->dataBuffer = nullptr;
+        }
+
+        if (context->cond != nullptr) {
+            MediaThreadCondDestroy(&context->cond);
+            context->cond = nullptr;
+        }
+    }
+}
+
+/**
+ * @brief 请求音频焦点
+ */
+static bool RequestMqttRecordAudioFocus(MqttRecordContext *context)
+{
+    bool success = AudioManagerInit();
+    if (!success) {
+        MEDIA_ERR_LOG("AudioManager init failed");
+        return false;
+    }
+
+    AudioSession sessionId = AudioManagerMakeSessionId();
+    if (sessionId == AUDIO_SESSION_ID_NONE) {
+        MEDIA_ERR_LOG("Audio session id invalid");
+        return false;
+    }
+
+    if (AudioManagerActivateInterrupt(AUDIO_STREAM_VOICE_RECORD, sessionId) == INTERRUPT_FAILED) {
+        MEDIA_ERR_LOG("Activate audio interrupt failed");
+        return false;
+    }
+
+    context->sessionId = sessionId;
+    return true;
+}
+
+/**
+ * @brief 释放音频焦点
+ */
+static bool ReleaseMqttRecordAudioFocus(void)
+{
+    if (AudioManagerDeactivateInterrupt() != 0) {
+        MEDIA_ERR_LOG("Deactivate audio interrupt failed");
+        return false;
+    }
+    return true;
+}
+
+/**
+ * @brief 启动录音流(根据宏选择使用 AudioStreamInInit 或 AudioCapturer)
+ */
+static int32_t StartMqttRecordStream(MqttRecordContext *context)
+{
+#if USE_AUDIO_STREAM_IN
+    // 使用 AudioStreamInInit 接口
+    CapturerInputConfig captureConfig = {};
+    captureConfig.audioFormat = context->audioFormat;
+    captureConfig.channelCount = context->channelCount;
+    captureConfig.linkDir = AUDIO_UP_LINK;
+    captureConfig.sampleRate = context->sampleRate;
+    captureConfig.sessionID = context->sessionId;
+    captureConfig.streamType = AUDIO_STREAM_VOICE_RECORD;
+
+    int32_t ret = AudioStreamInInit(captureConfig);
+    if (ret != 0) {
+        MEDIA_ERR_LOG("AudioStreamInInit failed: %d", ret);
+        return -1;
+    }
+
+    ret = AudioStreamInStart();
+    if (ret != 0) {
+        MEDIA_ERR_LOG("AudioStreamInStart failed: %d", ret);
+        AudioStreamInDeinit();
+        return -1;
+    }
+
+    context->streamInInitialized = true;
+    MEDIA_INFO_LOG("MQTT record stream started successfully (AudioStreamIn)");
+    return 0;
+#else
+    // 使用 AudioCapturer 接口(与 audio_capture_wrapper.cpp 一致)
+    // 创建音频采集器
+    context->audioCapturer = std::make_shared<OHOS::Audio::AudioCapturer>();
+    if (context->audioCapturer == nullptr || context->audioCapturer.get() == nullptr) {
+        MEDIA_ERR_LOG("Failed to create audio capturer");
+        return -1;
+    }
+
+    // 配置采集器参数(使用 AudioCapturerInfo,与 audio_capture_wrapper.cpp 一致)
+    AudioCapturerInfo info = {};
+    info.inputSource = AUDIO_MIC;
+    info.audioFormat = SBC;  // 硬编码为 SBC,用于排查 SBC 问题
+    info.sampleRate = context->sampleRate;
+    info.channelCount = context->channelCount;
+    info.streamType = AUDIO_STREAM_VOICE_RECORD;
+    info.bitWidth = BIT_WIDTH_16;  // 默认16位
+    info.sessionID = context->sessionId;
+
+    // 设置采集器信息
+    if (context->audioCapturer->SetCapturerInfo(info) != 0) {
+        MEDIA_ERR_LOG("Failed to set capturer info");
+        context->audioCapturer.reset();
+        context->audioCapturer = nullptr;
+        return -1;
+    }
+
+    // 获取帧数并计算帧大小(与 audio_capture_wrapper.cpp 一致)
+    size_t frameCount = context->audioCapturer->GetFrameCount();
+    if (frameCount == 0) {
+        MEDIA_ERR_LOG("Failed to get frame count");
+        context->audioCapturer->Release();
+        context->audioCapturer.reset();
+        context->audioCapturer = nullptr;
+        return -1;
+    }
+
+    context->framesize = frameCount * context->channelCount;
+    MEDIA_INFO_LOG("MQTT record frameCount: %zu, framesize: %zu", frameCount, context->framesize);
+
+    // 根据 framesize 重新分配缓冲区(如果现有缓冲区不够大)
+    if (context->bufferSize < context->framesize) {
+        if (context->dataBuffer != nullptr) {
+            free(context->dataBuffer);
+            context->dataBuffer = nullptr;
+        }
+        context->dataBuffer = (uint8_t*)malloc(context->framesize);
+        if (context->dataBuffer == nullptr) {
+            MEDIA_ERR_LOG("Failed to allocate buffer for framesize: %zu", context->framesize);
+            context->audioCapturer->Release();
+            context->audioCapturer.reset();
+            context->audioCapturer = nullptr;
+            return -1;
+        }
+        context->bufferSize = context->framesize;
+    }
+
+    // 启动采集器
+    if (!context->audioCapturer->Start()) {
+        MEDIA_ERR_LOG("Failed to start audio capturer");
+        context->audioCapturer->Release();
+        context->audioCapturer.reset();
+        context->audioCapturer = nullptr;
+        return -1;
+    }
+
+    MEDIA_INFO_LOG("MQTT record stream started successfully (AudioCapturer)");
+    return 0;
+#endif
+}
+
+/**
+ * @brief 录音主线程函数
+ */
+static void MqttRecordMainThread(void *priv)
+{
+    MqttRecordContext *context = g_mqttRecordContext;
+    if (context == nullptr) {
+        MEDIA_ERR_LOG("MQTT record context is null in main thread");
+        return;
+    }
+
+    // 请求音频焦点
+    bool success = RequestMqttRecordAudioFocus(context);
+    if (!success) {
+        MEDIA_ERR_LOG("Request audio focus failed");
+        return;
+    }
+
+    // 启动录音流
+    int32_t ret = StartMqttRecordStream(context);
+    if (ret != 0) {
+        MEDIA_ERR_LOG("Start record stream failed");
+        ReleaseMqttRecordAudioFocus();
+        return;
+    }
+
+    // 录音循环(根据宏选择使用 AudioStreamInObtainBuffer 或 AudioCapturer::Read)
+    while (!context->isRecordStopped) {
+#if USE_AUDIO_STREAM_IN
+        // 使用 AudioStreamInObtainBuffer 接口
+        if (context->streamInInitialized) {
+            uint32_t readSize = context->bufferSize;
+            int32_t ret = AudioStreamInObtainBuffer(context->dataBuffer, &readSize);
+            
+            if (ret == 0 && readSize > 0) {
+                // 保存数据到文件(用于验证数据正确性)
+                if (context->debugFile != nullptr) {
+                    size_t written = fwrite(context->dataBuffer, 1, readSize, context->debugFile);
+                    if (written != (size_t)readSize) {
+                        MEDIA_ERR_LOG("Failed to write to debug file: written=%zu, expected=%u", written, readSize);
+                    }
+                }
+                
+                if (context->dataCallback != nullptr) {
+                    context->dataCallback(context->dataBuffer, readSize, context->callbackUserData);
+                }
+            } else if (ret != 0) {
+                // 获取缓冲区失败,短暂休眠后继续
+                usleep(10*1000);  // 10ms
+                continue;
+            }
+        }
+#else
+        // 使用 AudioCapturer::Read 接口(与 audio_capture_wrapper.cpp 一致)
+        if (context->audioCapturer != nullptr) {
+            // 使用 Read 接口读取音频数据
+            int32_t readSize = context->audioCapturer->Read(context->dataBuffer, 
+                                                             context->framesize, 
+                                                             false);
+   
+            if (readSize > 0) {
+                // 保存数据到文件(用于验证数据正确性)
+                if (context->debugFile != nullptr) {
+                    size_t written = fwrite(context->dataBuffer, 1, readSize, context->debugFile);
+                    if (written != (size_t)readSize) {
+                        MEDIA_ERR_LOG("Failed to write to debug file: written=%zu, expected=%d", written, readSize);
+                    }
+                }
+                
+                if (context->dataCallback != nullptr) {
+                    context->dataCallback(context->dataBuffer, (uint32_t)readSize, context->callbackUserData);
+                }
+            } else if (readSize == ERR_RETRY_READ) {
+                // 需要重试,短暂休眠后继续(与 audio_capture_wrapper.cpp 一致)
+                usleep(10*1000);  // 10ms
+                continue;
+            }
+        }
+#endif
+
+        usleep(10*1000);
+    }
+
+    // 清理资源
+    DeinitMqttRecordResources(context);
+    ReleaseMqttRecordAudioFocus();
+
+    // 设置线程停止标志
+    g_mqttRecordThreadStopped = true;
+    
+    MEDIA_INFO_LOG("MQTT record main thread completed");
+}
+
+/**
+ * @brief 启动MQTT录音
+ * @param dataCallback 录音数据回调函数
+ * @param userData 用户数据指针
+ * @param audioParams 录音音频参数,为nullptr时使用默认参数
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StartRecord(MqttRecordDataCallback dataCallback, void* userData, 
+                         const MqttRecordAudioParams* audioParams)
+{
+    MEDIA_INFO_LOG("MQTT_StartRecord");
+
+    MediaMutexHandle mutex = GetMqttRecordMutex();
+    if (mutex == nullptr) {
+        MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+        return -1;
+    }
+
+    MediaMutexLock(mutex);
+    if (g_mqttRecordContext != nullptr) {
+        MEDIA_ERR_LOG("MQTT record already started");
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    // 分配上下文
+    g_mqttRecordContext = (MqttRecordContext *)malloc(sizeof(MqttRecordContext));
+    if (g_mqttRecordContext == nullptr) {
+        MEDIA_ERR_LOG("Failed to allocate MQTT record context");
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    if (memset_s(g_mqttRecordContext, sizeof(MqttRecordContext), 0, sizeof(MqttRecordContext)) != EOK) {
+        MEDIA_ERR_LOG("memset_s failed");
+        free(g_mqttRecordContext);
+        g_mqttRecordContext = nullptr;
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+    
+    // 初始化线程停止标志
+    g_mqttRecordThreadStopped = false;
+
+    // 设置回调
+    g_mqttRecordContext->dataCallback = dataCallback;
+    g_mqttRecordContext->callbackUserData = userData;
+
+    // 设置音频参数
+    if (audioParams != nullptr) {
+        g_mqttRecordContext->audioFormat = (AudioCodecFormat)audioParams->audioFormat;
+        g_mqttRecordContext->channelCount = audioParams->channelCount;
+        g_mqttRecordContext->sampleRate = audioParams->sampleRate;
+        MEDIA_INFO_LOG("Using custom audio params: format=%d, channels=%u, sampleRate=%u",
+                       audioParams->audioFormat, audioParams->channelCount, audioParams->sampleRate);
+    } else {
+        g_mqttRecordContext->audioFormat = MQTT_DEFAULT_AUDIO_FORMAT;
+        g_mqttRecordContext->channelCount = MQTT_DEFAULT_CHANNEL_COUNT;
+        g_mqttRecordContext->sampleRate = MQTT_DEFAULT_SAMPLE_RATE;
+        MEDIA_INFO_LOG("Using default audio params: format=%d, channels=%u, sampleRate=%u",
+                       MQTT_DEFAULT_AUDIO_FORMAT, MQTT_DEFAULT_CHANNEL_COUNT, MQTT_DEFAULT_SAMPLE_RATE);
+    }
+
+    // 初始化资源
+    if (!InitMqttRecordResources(g_mqttRecordContext)) {
+        MEDIA_ERR_LOG("Failed to init MQTT record resources");
+        free(g_mqttRecordContext);
+        g_mqttRecordContext = nullptr;
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    MediaMutexUnLock(mutex);
+
+    // 创建录音线程
+    app_task_definition_t task_cfg;
+    memset(&task_cfg, 0, sizeof(task_cfg));
+
+    task_cfg.create_queue_handle = NULL;
+    task_cfg.attr.name = "MqttRecordThread";
+    task_cfg.attr.priority = (osPriority_t)24;
+    task_cfg.attr.stack_size = 0x2000;  // 8KB
+    task_cfg.func = MqttRecordMainThread;
+    task_cfg.use_mem = USE_EXTEND_MEM;
+
+    extern errcode_t uapi_create_osThread_custom(app_task_definition_t* task_cfg);
+    errcode_t ret = uapi_create_osThread_custom(&task_cfg);
+
+    if (ret != ERRCODE_SUCC) {
+        MEDIA_ERR_LOG("Failed to create MQTT record thread: %d", ret);
+        MediaMutexLock(mutex);
+        DeinitMqttRecordResources(g_mqttRecordContext);
+        free(g_mqttRecordContext);
+        g_mqttRecordContext = nullptr;
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    // 保存线程句柄
+    g_mqttRecordContext->taskHandle = (void*)task_cfg.task_handle;
+    strncpy(g_mqttRecordContext->threadName, task_cfg.attr.name, sizeof(g_mqttRecordContext->threadName) - 1);
+    g_mqttRecordContext->threadName[sizeof(g_mqttRecordContext->threadName) - 1] = '\0';
+
+    MEDIA_INFO_LOG("MQTT record started successfully");
+    return 0;
+}
+
+/**
+ * @brief 停止MQTT录音
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StopRecord(void)
+{
+    MEDIA_INFO_LOG("MQTT_StopRecord");
+
+    MediaMutexHandle mutex = GetMqttRecordMutex();
+    if (mutex == nullptr) {
+        MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+        return -1;
+    }
+
+    MediaMutexLock(mutex);
+    if (g_mqttRecordContext == nullptr) {
+        MEDIA_ERR_LOG("MQTT record not started");
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    if (g_mqttRecordContext->isRecordStopped) {
+        MEDIA_ERR_LOG("MQTT record already stopped");
+        MediaMutexUnLock(mutex);
+        return 0;
+    }
+
+    // 设置停止标志
+    g_mqttRecordContext->isRecordStopped = true;
+    MediaMutexUnLock(mutex);
+
+    // 等待线程结束
+    MEDIA_INFO_LOG("Waiting for MQTT record thread to stop...");
+    
+    if (g_mqttRecordContext->taskHandle != nullptr) {
+        osThreadId_t threadId = (osThreadId_t)g_mqttRecordContext->taskHandle;
+        const char* threadName = g_mqttRecordContext->threadName;
+        
+        // 验证线程ID和名称是否匹配,避免ID被复用
+        bool isValid = true;
+        if (threadName != nullptr && threadName[0] != '\0') {
+            osThreadState_t threadState = osThreadGetState(threadId);
+            if (threadState == osThreadError) {
+                isValid = false;  // 线程不存在或无效
+            } else {
+                const char* actualName = osThreadGetName(threadId);
+                if (actualName == nullptr || strcmp(actualName, threadName) != 0) {
+                    isValid = false;  // 线程名称不匹配
+                }
+            }
+        }
+        
+        if (!isValid) {
+            MEDIA_INFO_LOG("Thread ID may have been reused, thread name mismatch. Expected: %s", 
+                          threadName ? threadName : "unknown");
+            MEDIA_INFO_LOG("Assuming thread already stopped due to ID reuse");
+        } else {
+            MEDIA_INFO_LOG("Thread validation passed, waiting for thread: %s", 
+                          threadName ? threadName : "unknown");
+            
+            // 首先尝试使用 osThreadJoin 等待线程结束
+            osStatus_t joinStatus = osThreadJoin(threadId);
+            if (joinStatus == osOK) {
+                MEDIA_INFO_LOG("MQTT record thread stopped successfully (osThreadJoin)");
+            } else {
+                // 如果 osThreadJoin 不可用或失败,使用状态检查
+                MEDIA_INFO_LOG("osThreadJoin failed (%d), using state check...", joinStatus);
+                
+                // 使用 osThreadGetState 检查线程状态
+                for (int i = 0; i < 500; i++) {
+                    usleep(1000*1000);  // 100ms
+                    
+                    // 再次验证线程,防止在等待过程中ID被复用
+                    if (threadName != nullptr && threadName[0] != '\0') {
+                        osThreadState_t checkState = osThreadGetState(threadId);
+                        if (checkState == osThreadError) {
+                            MEDIA_INFO_LOG("Thread ID invalid during wait, stopping check");
+                            usleep(1000*1000);  // 100ms
+
+                            break;
+                        }
+                        const char* checkName = osThreadGetName(threadId);
+                        if (checkName == nullptr || strcmp(checkName, threadName) != 0) {
+                            if (g_mqttRecordThreadStopped) {
+                                MEDIA_INFO_LOG("Thread ID reused during wait, stopping check");
+                                usleep(1000*1000);  // 100ms
+
+                                break;
+                            }
+                        }
+                    }
+                    
+                    osThreadState_t threadState = osThreadGetState(threadId);
+                    
+                    // 检查线程状态,如果线程不存在或已终止,则认为已停止
+                    bool thread_running = (threadState == osThreadReady || 
+                                         threadState == osThreadRunning || 
+                                         threadState == osThreadBlocked);
+                    
+                    MEDIA_INFO_LOG("Waiting... %d/50 (state: %d, running: %s, stopped_flag: %d)", 
+                                  i + 1, threadState, thread_running ? "yes" : "no", 
+                                  g_mqttRecordThreadStopped ? 1 : 0);
+                    
+                    if (!thread_running && g_mqttRecordThreadStopped) {
+                        MEDIA_INFO_LOG("MQTT record thread stopped successfully (state check)");
+                        usleep(1000*1000);  // 100ms
+
+                        break;
+                    }
+                }
+            }
+        }
+    } else {
+        MEDIA_INFO_LOG("No valid thread handle, assuming thread already stopped");
+    }
+
+    MEDIA_INFO_LOG("MQTT record stopped and resources cleaned up");
+    return 0;
+}
+
+/**
+ * @brief 检查MQTT录音是否正在运行
+ * @return true 正在运行,false 未运行
+ */
+bool MQTT_IsRecordRunning(void)
+{
+    bool isRunning = false;
+
+    MediaMutexHandle mutex = GetMqttRecordMutex();
+    if (mutex == nullptr) {
+        return false;
+    }
+
+    MediaMutexLock(mutex);
+    if (g_mqttRecordContext != nullptr && !g_mqttRecordContext->isRecordStopped) {
+        isRunning = true;
+    }
+    MediaMutexUnLock(mutex);
+
+    return isRunning;
+}
+
+/**
+ * @brief 获取MQTT录音参数
+ * @param audioParams 输出参数:当前录音音频参数
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetRecordParams(MqttRecordAudioParams* audioParams)
+{
+    if (audioParams == nullptr) {
+        MEDIA_ERR_LOG("Invalid output parameter");
+        return -1;
+    }
+
+    MediaMutexHandle mutex = GetMqttRecordMutex();
+    if (mutex == nullptr) {
+        MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+        return -1;
+    }
+
+    MediaMutexLock(mutex);
+    if (g_mqttRecordContext == nullptr) {
+        MEDIA_ERR_LOG("MQTT record not started");
+        MediaMutexUnLock(mutex);
+        return -1;
+    }
+
+    audioParams->audioFormat = (int32_t)g_mqttRecordContext->audioFormat;
+    audioParams->channelCount = g_mqttRecordContext->channelCount;
+    audioParams->sampleRate = g_mqttRecordContext->sampleRate;
+
+    MediaMutexUnLock(mutex);
+    return 0;
+}
+
+// ==================== 音频播放接口 ====================
+
+// 播放回调函数类型
+typedef void (*MqttPlayerCallback)(int32_t event, void* userData);
+
+// 播放事件定义
+enum MqttPlayerEvent {
+    MQTT_PLAYER_EVENT_PLAY = 0,
+    MQTT_PLAYER_EVENT_PAUSE,
+    MQTT_PLAYER_EVENT_STOP,
+    MQTT_PLAYER_EVENT_COMPLETE,
+    MQTT_PLAYER_EVENT_ERROR
+};
+
+// 播放回调实现类
+class MqttPlayerCallbackImpl : public AudioPlayerServiceCallback {
+public:
+    MqttPlayerCallbackImpl() : callback_(nullptr), userData_(nullptr) {}
+    ~MqttPlayerCallbackImpl() override {}
+    
+    void SetCallback(MqttPlayerCallback cb, void* userData) {
+        callback_ = cb;
+        userData_ = userData;
+    }
+    
+    void OnInterrupt(int32_t type, int32_t hint) override {
+        MEDIA_INFO_LOG("OnInterrupt type[%d], hint[%d]", type, hint);
+        if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) {
+            AudioPlayerService::GetInstance()->Pause();
+        } else if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) {
+            AudioPlayerService::GetInstance()->Resume();
+        } else if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP) {
+            AudioPlayerService::GetInstance()->Reset();
+        }
+    }
+    
+    void OnError(int32_t errorType, int32_t errorCode) override {
+        MEDIA_ERR_LOG("OnError errorType[%d], errorCode[%d]", errorType, errorCode);
+        if (callback_ != nullptr) {
+            callback_(MQTT_PLAYER_EVENT_ERROR, userData_);
+        }
+        AudioPlayerService::GetInstance()->Reset();
+    }
+    
+    void OnPlaybackComplete() override {
+        MEDIA_INFO_LOG("OnPlaybackComplete");
+        if (callback_ != nullptr) {
+            callback_(MQTT_PLAYER_EVENT_COMPLETE, userData_);
+        }
+    }
+    
+    void OnPlay() override {
+        MEDIA_INFO_LOG("OnPlay");
+        if (callback_ != nullptr) {
+            callback_(MQTT_PLAYER_EVENT_PLAY, userData_);
+        }
+    }
+    
+    void OnPause() override {
+        MEDIA_INFO_LOG("OnPause");
+        if (callback_ != nullptr) {
+            callback_(MQTT_PLAYER_EVENT_PAUSE, userData_);
+        }
+    }
+    
+    void OnStop() override {
+        MEDIA_INFO_LOG("OnStop");
+        if (callback_ != nullptr) {
+            callback_(MQTT_PLAYER_EVENT_STOP, userData_);
+        }
+    }
+    
+private:
+    MqttPlayerCallback callback_;
+    void* userData_;
+};
+
+// 全局播放回调实例
+static std::shared_ptr<MqttPlayerCallbackImpl> g_mqttPlayerCallback = nullptr;
+
+/**
+ * @brief 播放指定路径的音频文件
+ * @param filePath 音频文件路径
+ * @param callback 播放事件回调函数(可为nullptr)
+ * @param userData 用户数据指针
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_PlayAudioFile(const char* filePath, MqttPlayerCallback callback, void* userData)
+{
+    if (filePath == nullptr || strlen(filePath) == 0) {
+        MEDIA_ERR_LOG("Invalid file path");
+        return -1;
+    }
+    
+    MEDIA_INFO_LOG("MQTT_PlayAudioFile: %s", filePath);
+    
+    // 创建回调实例
+    if (g_mqttPlayerCallback == nullptr) {
+        g_mqttPlayerCallback = std::make_shared<MqttPlayerCallbackImpl>();
+    }
+    g_mqttPlayerCallback->SetCallback(callback, userData);
+    
+    // 设置回调
+    AudioPlayerService::GetInstance()->SetAudioPlayerCallback(g_mqttPlayerCallback);
+    
+    // 设置播放源
+    std::string src(filePath);
+    int32_t ret = AudioPlayerService::GetInstance()->SetPlaySource(src);
+    if (ret != MEDIA_OK) {
+        MEDIA_ERR_LOG("Failed to set play source: %s", filePath);
+        return -1;
+    }
+    
+    // 开始播放
+    ret = AudioPlayerService::GetInstance()->Start();
+    if (ret != MEDIA_OK) {
+        MEDIA_ERR_LOG("Failed to start playback");
+        return -1;
+    }
+    
+    MEDIA_INFO_LOG("Audio playback started: %s", filePath);
+    return 0;
+}
+
+/**
+ * @brief 停止当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StopAudioPlay(void)
+{
+    MEDIA_INFO_LOG("MQTT_StopAudioPlay");
+    return AudioPlayerService::GetInstance()->Reset();
+}
+
+/**
+ * @brief 暂停当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_PauseAudioPlay(void)
+{
+    MEDIA_INFO_LOG("MQTT_PauseAudioPlay");
+    return AudioPlayerService::GetInstance()->Pause();
+}
+
+/**
+ * @brief 恢复当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_ResumeAudioPlay(void)
+{
+    MEDIA_INFO_LOG("MQTT_ResumeAudioPlay");
+    return AudioPlayerService::GetInstance()->Resume();
+}
+
+/**
+ * @brief 跳转到指定位置
+ * @param mSeconds 目标位置(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_SeekAudioPlay(int64_t mSeconds)
+{
+    MEDIA_INFO_LOG("MQTT_SeekAudioPlay: %lld ms", mSeconds);
+    return AudioPlayerService::GetInstance()->Seek(mSeconds);
+}
+
+/**
+ * @brief 获取当前播放时间
+ * @param time 输出参数:当前播放时间(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetCurrentTime(int64_t* time)
+{
+    if (time == nullptr) {
+        MEDIA_ERR_LOG("Invalid output parameter");
+        return -1;
+    }
+    
+    int64_t currentTime = 0;
+    int32_t ret = AudioPlayerService::GetInstance()->GetCurrentTime(currentTime);
+    if (ret != MEDIA_OK) {
+        MEDIA_ERR_LOG("Failed to get current time");
+        return -1;
+    }
+    
+    *time = currentTime;
+    return 0;
+}
+
+/**
+ * @brief 获取音频文件总时长
+ * @param duration 输出参数:总时长(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetDuration(int64_t* duration)
+{
+    if (duration == nullptr) {
+        MEDIA_ERR_LOG("Invalid output parameter");
+        return -1;
+    }
+    
+    int64_t durationMs = -1;
+    int32_t ret = AudioPlayerService::GetInstance()->GetDuration(durationMs);
+    if (ret != MEDIA_OK) {
+        MEDIA_ERR_LOG("Failed to get duration");
+        return -1;
+    }
+    
+    *duration = durationMs;
+    return 0;
+}
+
+/**
+ * @brief 检查是否正在播放
+ * @return true 正在播放,false 未播放
+ */
+bool MQTT_IsPlaying(void)
+{
+    return AudioPlayerService::GetInstance()->IsPlaying();
+}
+
+/**
+ * @brief 获取当前播放状态
+ * @return 播放状态值
+ */
+int32_t MQTT_GetPlayStatus(void)
+{
+    return AudioPlayerService::GetInstance()->GetPlayStatus();
+}
+
+/**
+ * @brief 设置单曲循环模式
+ * @param enable true 开启单曲循环,false 关闭
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_SetSingleLoop(bool enable)
+{
+    MEDIA_INFO_LOG("MQTT_SetSingleLoop: %s", enable ? "true" : "false");
+    OHOS::AudioPlayerLoopMode loopMode = enable ? OHOS::AudioPlayerLoopMode::AUDIO_PLAYER_SINGLE_LOOP 
+                                                 : OHOS::AudioPlayerLoopMode::AUDIO_PLAYER_INVAILD_LOOP;
+    return AudioPlayerService::GetInstance()->SetPlayLoopMode(loopMode);
+}
+
+// ==================== OGG 封装接口(独立接口,用于将 OPUS 数据封装为 OGG 文件)====================
+
+// OGG 上下文管理器(用于 ln_UDP.c,避免其直接依赖 ogg.h)
+static MqttOggContext g_ln_udp_ogg_ctx = {0};  // 全局 OGG 上下文(用于 UDP 接收)
+
+// 前向声明内部函数
+static int32_t MqttOggEncapsulationInit(MqttOggContext *oggCtx, FILE *pfd, uint32_t sampleRate, uint32_t channelCount);
+static int32_t MqttOggEncapsulationWrite(MqttOggContext *oggCtx, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos);
+static int32_t MqttOggEncapsulationFinish(MqttOggContext *oggCtx, FILE *pfd);
+
+/**
+ * @brief 获取全局 OGG 上下文句柄(供 ln_UDP.c 使用)
+ * @return OGG 上下文句柄(不透明指针),失败返回 nullptr
+ */
+extern "C" void* MqttOggGetContext(void)
+{
+    return (void*)&g_ln_udp_ogg_ctx;
+}
+
+/**
+ * @brief 初始化 OGG 封装上下文(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针(由调用者分配,大小至少为 sizeof(MqttOggContext))
+ * @param pfd 输出文件句柄(已打开的文件,用于写入 OGG 数据)
+ * @param sampleRate 采样率
+ * @param channelCount 声道数
+ * @return 0 成功,-1 失败
+ * @note 调用此函数前需要先打开文件并获取文件句柄
+ */
+static int32_t MqttOggEncapsulationInit(MqttOggContext *oggCtx, FILE *pfd, uint32_t sampleRate, uint32_t channelCount)
+{
+    if (oggCtx == nullptr || pfd == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for init");
+        return -1;
+    }
+
+    // 分配 packet 和 page
+    oggCtx->packet = (ogg_packet *)MqttOggMemCalloc(sizeof(ogg_packet));
+    if (oggCtx->packet == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Failed to allocate packet");
+        return -1;
+    }
+    
+    oggCtx->page = (ogg_page *)MqttOggMemCalloc(sizeof(ogg_page));
+    if (oggCtx->page == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Failed to allocate page");
+        MqttOggMemFree((void **)&oggCtx->packet);
+        return -1;
+    }
+
+    // 初始化 OGG 上下文
+    oggCtx->sampleRate = sampleRate;
+    oggCtx->channels = channelCount;
+    oggCtx->granulepos = -1;  // -1 means start page
+    oggCtx->packetCount = 0;
+    oggCtx->isEnd = false;
+    oggCtx->serialno = 0x1;  // unique serialno
+    
+    if (ogg_stream_init(&oggCtx->oggStream, oggCtx->serialno) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: ogg stream init failed");
+        MqttOggMemFree((void **)&oggCtx->packet);
+        MqttOggMemFree((void **)&oggCtx->page);
+        return -1;
+    }
+
+    // 初始化 OGG 头部
+    if (MqttOggHeaderInit(oggCtx, sampleRate, channelCount) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: Header init failed");
+        ogg_stream_clear(&oggCtx->oggStream);
+        MqttOggMemFree((void **)&oggCtx->packet);
+        MqttOggMemFree((void **)&oggCtx->page);
+        return -1;
+    }
+
+    // 写入 ID Header packet
+    oggCtx->packet->packet = oggCtx->idHeader;
+    oggCtx->packet->bytes = MQTT_OGG_OPUS_ID_HEADER_LEN;
+    oggCtx->packet->b_o_s = 1;  // 1 means beginning of ogg stream
+    oggCtx->packet->e_o_s = 0;
+    oggCtx->packet->granulepos = oggCtx->granulepos;
+    oggCtx->packet->packetno = oggCtx->packetCount++;
+    oggCtx->granulepos = 0;
+    ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+    
+    if (MqttOggStreamFlush(oggCtx, pfd) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: Flush ID header failed");
+        ogg_stream_clear(&oggCtx->oggStream);
+        MqttOggMemFree((void **)&oggCtx->packet);
+        MqttOggMemFree((void **)&oggCtx->page);
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        MqttOggMemFree((void **)&oggCtx->commentHeader);
+        return -1;
+    }
+
+    // 写入 Comment Header packet
+    oggCtx->packet->packet = oggCtx->commentHeader;
+    oggCtx->packet->bytes = MQTT_OGG_OPUS_COMMENT_HEADER_LEN;
+    oggCtx->packet->b_o_s = 0;
+    oggCtx->packet->e_o_s = 0;
+    oggCtx->packet->granulepos = 0;
+    oggCtx->packet->packetno = oggCtx->packetCount++;
+    ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+    
+    if (MqttOggStreamFlush(oggCtx, pfd) != 0) {
+        MEDIA_ERR_LOG("MQTT OGG: Flush comment header failed");
+        ogg_stream_clear(&oggCtx->oggStream);
+        MqttOggMemFree((void **)&oggCtx->packet);
+        MqttOggMemFree((void **)&oggCtx->page);
+        MqttOggMemFree((void **)&oggCtx->idHeader);
+        MqttOggMemFree((void **)&oggCtx->commentHeader);
+        return -1;
+    }
+
+    oggCtx->initialized = true;
+    MEDIA_INFO_LOG("MQTT OGG: Encapsulation initialized successfully");
+    return 0;
+}
+
+/**
+ * @brief 写入音频数据到 OGG 封装(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针
+ * @param buffer 音频数据缓冲区(包含 OPUS 编码头,前8字节为编码头)
+ * @param bufferLen 数据长度(包含编码头)
+ * @param pfd 输出文件句柄
+ * @param isEos 是否为结束标志
+ * @return 0 成功,-1 失败
+ * @note buffer 的前 8 字节为 OPUS 编码头,实际 OPUS 数据从 buffer[8] 开始
+ */
+static int32_t MqttOggEncapsulationWrite(MqttOggContext *oggCtx, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos)
+{
+    if (oggCtx == nullptr || buffer == nullptr || pfd == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for write");
+        return -1;
+    }
+
+    if (!oggCtx->initialized) {
+        MEDIA_ERR_LOG("MQTT OGG: Context not initialized");
+        return -1;
+    }
+
+    if (bufferLen < MQTT_OGG_OPUS_ENCODE_HEADER_SIZE) {
+        MEDIA_ERR_LOG("MQTT OGG: Buffer too small for OPUS encode header");
+        return -1;
+    }
+
+    // 构造 OGG packet(跳过 OPUS 编码头)
+    oggCtx->packet->packet = (unsigned char *)(buffer + MQTT_OGG_OPUS_ENCODE_HEADER_SIZE);
+    oggCtx->packet->bytes = bufferLen - MQTT_OGG_OPUS_ENCODE_HEADER_SIZE;
+    oggCtx->packet->b_o_s = 0;
+    oggCtx->packet->e_o_s = isEos ? 1 : 0;
+    oggCtx->packet->granulepos = oggCtx->granulepos;
+    oggCtx->packet->packetno = oggCtx->packetCount++;
+    // 计算 granulepos(假设每帧 10ms,采样率为 OPUS_SAMPLERATE)
+    oggCtx->granulepos += MQTT_OGG_OPUS_SAMPLERATE * 10 / MQTT_OGG_MILLSECOND_TO_SECOND;
+    
+    ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+    
+    if (!isEos) {
+        return MqttOggWritePage(oggCtx, pfd);
+    } else {
+        return MqttOggStreamFlush(oggCtx, pfd);
+    }
+}
+
+/**
+ * @brief 结束 OGG 封装并清理资源(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针
+ * @param pfd 输出文件句柄(用于最终刷新,可为 nullptr)
+ * @return 0 成功,-1 失败
+ * @note 调用此函数后,需要调用者自行关闭文件句柄
+ */
+static int32_t MqttOggEncapsulationFinish(MqttOggContext *oggCtx, FILE *pfd)
+{
+    if (oggCtx == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context for finish");
+        return -1;
+    }
+
+    if (!oggCtx->initialized) {
+        MEDIA_ERR_LOG("MQTT OGG: Context not initialized, nothing to finish");
+        return 0;  // 未初始化,直接返回成功
+    }
+
+    // 如果文件句柄有效,进行最终刷新
+    if (pfd != nullptr) {
+        MqttOggStreamFlush(oggCtx, pfd);
+    }
+
+    // 清理资源
+    oggCtx->sampleRate = 0;
+    oggCtx->channels = 0;
+    oggCtx->granulepos = 0;
+    oggCtx->packetCount = 0;
+    oggCtx->isEnd = false;
+    
+    MqttOggMemFree((void **)&oggCtx->packet);
+    MqttOggMemFree((void **)&oggCtx->page);
+    MqttOggMemFree((void **)&oggCtx->idHeader);
+    MqttOggMemFree((void **)&oggCtx->commentHeader);
+    
+    ogg_stream_clear(&oggCtx->oggStream);
+    oggCtx->initialized = false;
+    
+    MEDIA_INFO_LOG("MQTT OGG: Encapsulation finished and resources cleaned");
+    return 0;
+}
+
+/**
+ * @brief 初始化 OGG 封装上下文(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param pfd 输出文件句柄(已打开的文件,用于写入 OGG 数据)
+ * @param sampleRate 采样率
+ * @param channelCount 声道数
+ * @return 0 成功,-1 失败
+ * @note 调用此函数前需要先打开文件并获取文件句柄
+ */
+extern "C" int32_t MqttOggEncapsulationInitHandle(void* oggCtxHandle, FILE *pfd, uint32_t sampleRate, uint32_t channelCount)
+{
+    if (oggCtxHandle == nullptr || pfd == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for init");
+        return -1;
+    }
+    
+    MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+    return MqttOggEncapsulationInit(oggCtx, pfd, sampleRate, channelCount);
+}
+
+/**
+ * @brief 写入音频数据到 OGG 封装(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param buffer 音频数据缓冲区(包含 OPUS 编码头,前8字节为编码头)
+ * @param bufferLen 数据长度(包含编码头)
+ * @param pfd 输出文件句柄
+ * @param isEos 是否为结束标志
+ * @return 0 成功,-1 失败
+ * @note buffer 的前 8 字节为 OPUS 编码头,实际 OPUS 数据从 buffer[8] 开始
+ */
+extern "C" int32_t MqttOggEncapsulationWriteHandle(void* oggCtxHandle, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos)
+{
+    if (oggCtxHandle == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context handle for write");
+        return -1;
+    }
+    
+    MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+    return MqttOggEncapsulationWrite(oggCtx, buffer, bufferLen, pfd, isEos);
+}
+
+/**
+ * @brief 结束 OGG 封装并清理资源(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param pfd 输出文件句柄(用于最终刷新,可为 nullptr)
+ * @return 0 成功,-1 失败
+ * @note 调用此函数后,需要调用者自行关闭文件句柄
+ */
+extern "C" int32_t MqttOggEncapsulationFinishHandle(void* oggCtxHandle, FILE *pfd)
+{
+    if (oggCtxHandle == nullptr) {
+        MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context handle for finish");
+        return -1;
+    }
+    
+    MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+    return MqttOggEncapsulationFinish(oggCtx, pfd);
+}
+
+#ifdef __cplusplus
+};
+#endif
+
index 4719195..f8e1243 100644 (file)
@@ -27,6 +27,18 @@ set(SOURCES
         
 )
 
+# LN_MQTT:根据 SUPPORT_LN_MQTT_SERVICE 灵活添加
+# - 该宏通常来自 target_config 的 DEFINES 列表(由构建系统注入到 CMake 变量 DEFINES 中)
+# - 兼容:如果外部直接以 -DSUPPORT_LN_MQTT_SERVICE=1 形式传入,也可生效
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+    list(APPEND SOURCES
+        ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_mqtt_api.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_mqtt_api_at.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_OTA.c
+        ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_UDP.c
+    )
+endif()
+
 # 公共头文件路径(供其他模块引用)
 set(PUBLIC_HEADER
     ${ROOT_DIR}/zhihui/4g/cat1Service/include/
@@ -37,6 +49,7 @@ set(PUBLIC_HEADER
     ${ROOT_DIR}/open_source/openharmony/foundation/ace/ace_engine_lite/modules/netstack/websocket/include
     ${ROOT_DIR}/zhihui/websocket/os_ws
     ${ROOT_DIR}/application/wearable/ln/nativeapp/nativeui/include/bluetooth
+    ${ROOT_DIR}/open_source/openharmony/foundation/ace/ace_engine_lite/modules/netstack/http/include
 )
 
 # 公共宏定义(可选)
@@ -52,11 +65,29 @@ set(PRIVATE_HEADER
     ${CMAKE_CURRENT_SOURCE_DIR}/
 )
 
+# LN_MQTT 头文件路径(仅在使能时添加,避免无关组件污染 include path)
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+    set(PRIVATE_HEADER
+        ${PRIVATE_HEADER}
+        ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT
+        ${ROOT_DIR}/zhihui/test_opus_frame_to_pcm/include
+    )
+endif()
+
 # 私有宏定义(可选)
 set(PRIVATE_DEFINES
     # 如无特殊私有宏,可留空
 )
 
+# LN_MQTT 双流接口开关(仅在使能 LN_MQTT 时添加)
+# 定义 USE_DUAL_STREAM_INTERFACE=1 使用双流接口,否则使用 MQTT_StartRecord
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+    if((DEFINED USE_DUAL_STREAM_INTERFACE AND USE_DUAL_STREAM_INTERFACE) OR ("USE_DUAL_STREAM_INTERFACE" IN_LIST DEFINES))
+        list(APPEND PRIVATE_DEFINES USE_DUAL_STREAM_INTERFACE=1)
+        message(STATUS "[LN_MQTT] Dual stream interface enabled")
+    endif()
+endif()
+
 # 公共编译选项(可选)
 set(COMPONENT_PUBLIC_CCFLAGS
 )
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_OTA.c b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_OTA.c
new file mode 100644 (file)
index 0000000..1f5a100
--- /dev/null
@@ -0,0 +1,389 @@
+
+#include "httpclient.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "cJSON.h"
+#include "ln_api.h"
+// #include "ppp_lwip.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// MQTT 凭证结构体
+typedef struct {
+    char endpoint[256];
+    char client_id[256];
+    char username[256];
+    char password[256];
+    char publish_topic[128];
+    char subscribe_topic[128];
+} mqtt_credentials_t;
+
+// http://115.190.94.208:8085/api/v1/ota
+
+// 保存 MQTT 凭证到文件
+static int save_mqtt_credentials(const mqtt_credentials_t *cred)
+{
+    if (!cred) {
+        return -1;
+    }
+
+    FILE *fp = fopen("/user/mqtt_credentials.json", "w");
+    if (!fp) {
+        printf("Failed to open mqtt credentials file for writing\n");
+        return -1;
+    }
+
+    cJSON *root = cJSON_CreateObject();
+    cJSON *mqtt = cJSON_CreateObject();
+    
+    cJSON_AddStringToObject(mqtt, "endpoint", cred->endpoint);
+    cJSON_AddStringToObject(mqtt, "client_id", cred->client_id);
+    cJSON_AddStringToObject(mqtt, "username", cred->username);
+    cJSON_AddStringToObject(mqtt, "password", cred->password);
+    cJSON_AddStringToObject(mqtt, "publish_topic", cred->publish_topic);
+    cJSON_AddStringToObject(mqtt, "subscribe_topic", cred->subscribe_topic);
+    
+    cJSON_AddItemToObject(root, "mqtt", mqtt);
+    
+    char *json_str = cJSON_Print(root);
+    if (json_str) {
+        fputs(json_str, fp);
+        cJSON_free(json_str);
+    }
+    
+    cJSON_Delete(root);
+    fclose(fp);
+    
+    printf("MQTT credentials saved successfully\n");
+    return 0;
+}
+
+/**
+ * @brief 从响应 JSON 中提取 MQTT 凭证
+ * @param response_json 服务器响应的 JSON 字符串
+ * @param credentials 输出的 MQTT 凭证结构体指针
+ * @return 0 成功,-1 失败
+ */
+static int extract_mqtt_credentials(const char *response_json, mqtt_credentials_t *credentials)
+{
+    if (!response_json || !credentials) {
+        printf("Invalid parameters for extract_mqtt_credentials\n");
+        return -1;
+    }
+    
+    // 解析响应 JSON
+    cJSON *root = cJSON_Parse(response_json);
+    if (!root) {
+        printf("Failed to parse response JSON\n");
+        return -1;
+    }
+    
+    // 提取 MQTT 凭证
+    cJSON *mqtt_obj = cJSON_GetObjectItem(root, "mqtt");
+    if (!mqtt_obj || !cJSON_IsObject(mqtt_obj)) {
+        printf("No 'mqtt' object found in response\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    // 初始化凭证结构体
+    memset(credentials, 0, sizeof(mqtt_credentials_t));
+    
+    // 提取各个字段
+    cJSON *item = cJSON_GetObjectItem(mqtt_obj, "endpoint");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->endpoint, item->valuestring, sizeof(credentials->endpoint) - 1);
+        credentials->endpoint[sizeof(credentials->endpoint) - 1] = '\0';
+    }
+    
+    item = cJSON_GetObjectItem(mqtt_obj, "client_id");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->client_id, item->valuestring, sizeof(credentials->client_id) - 1);
+        credentials->client_id[sizeof(credentials->client_id) - 1] = '\0';
+    }
+    
+    item = cJSON_GetObjectItem(mqtt_obj, "username");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->username, item->valuestring, sizeof(credentials->username) - 1);
+        credentials->username[sizeof(credentials->username) - 1] = '\0';
+    }
+    
+    item = cJSON_GetObjectItem(mqtt_obj, "password");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->password, item->valuestring, sizeof(credentials->password) - 1);
+        credentials->password[sizeof(credentials->password) - 1] = '\0';
+    }
+    
+    item = cJSON_GetObjectItem(mqtt_obj, "publish_topic");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->publish_topic, item->valuestring, sizeof(credentials->publish_topic) - 1);
+        credentials->publish_topic[sizeof(credentials->publish_topic) - 1] = '\0';
+    }
+    
+    item = cJSON_GetObjectItem(mqtt_obj, "subscribe_topic");
+    if (item && cJSON_IsString(item) && item->valuestring) {
+        strncpy(credentials->subscribe_topic, item->valuestring, sizeof(credentials->subscribe_topic) - 1);
+        credentials->subscribe_topic[sizeof(credentials->subscribe_topic) - 1] = '\0';
+    }
+    
+    cJSON_Delete(root);
+    
+    printf("MQTT credentials extracted successfully\n");
+    return 0;
+}
+
+// 数据
+// {
+//   "version": 3,
+//   "application": {
+//     "idf_version": "5.1.2",
+//     "elf_sha256": "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb"
+//   },
+//   "ota": {
+//     "label": "ota_0"
+//   },
+//   "board": {
+//     "type": "bread-compact-wifi",
+//     "ip": "192.168.2.100",
+//     "mac": "8c:85:90:65:53:8d"
+//   }
+// }
+
+//回复
+
+// {
+//   "mqtt": {
+//     "endpoint": "192.168.2.200:1883",
+//     "client_id": "GID_test@@@8c_85_90_65_53_8d@@@63a2c34b-fa85-4e4b-a289-7eb562e545ae",
+//     "username": "eyJpcCI6IjE5Mi4xNjguMi4xMDAifQ==",
+//     "password": "VMLUCd86BtIYg9kBRQ9b6K7HyFyP4vnqWf0giGClMK8=",
+//     "publish_topic": "device-server",
+//     "subscribe_topic": ""
+//   },
+//   "server_time": {
+//     "timestamp": 1733760000000,
+//     "timezone_offset": 480
+//   },
+//   "firmware": {
+//     "version": "2.0.1",
+//     "url": "https://example.com/firmware/2.0.1.bin"
+//   },
+//   "websocket": {
+//     "url": "wss://api.example.com/ws",
+//     "token": "xxx"
+//   },
+//   "activation": {
+//     "code": "ABCD1234",
+//     "message": "请在APP中输入激活码",
+//     "challenge": "xxx",
+//     "timeout_ms": 300000
+//   }
+// }
+
+/**
+ * @brief 构建设备信息JSON并发送到服务器
+ * @param url 服务器URL(如果为NULL,使用默认URL: http://115.190.94.208:8085/api/v1/ota)
+ * @param credentials 输出的MQTT凭证(可以为NULL)
+ * @return 0 成功,-1 失败
+ * 
+ * 根据以下格式构建设备信息JSON:
+ * {
+ *   "version": 3,
+ *   "application": {
+ *     "idf_version": "5.1.2",
+ *     "elf_sha256": "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb"
+ *   },
+ *   "ota": {
+ *     "label": "ota_0"
+ *   },
+ *   "board": {
+ *     "type": "bread-compact-wifi",
+ *     "ip": "192.168.2.100",
+ *     "mac": "8c:85:90:65:53:8d"
+ *   }
+ * }
+ */
+int ln_ota_send_device_info_json(const char *url, void *credentials)
+{
+    const char *default_url = "http://115.190.94.208:8085/api/v1/ota";
+    const char *target_url = url ? url : default_url;
+    
+    // 构建设备信息JSON
+    cJSON *root = cJSON_CreateObject();
+    if (!root) {
+        printf("[LN_OTA] Failed to create JSON root object\n");
+        return -1;
+    }
+    
+    // version
+    cJSON_AddNumberToObject(root, "version", 3);
+    
+    // application
+    cJSON *application = cJSON_CreateObject();
+    if (!application) {
+        cJSON_Delete(root);
+        return -1;
+    }
+    cJSON_AddStringToObject(application, "idf_version", "5.1.2");
+    cJSON_AddStringToObject(application, "elf_sha256", "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb");
+    cJSON_AddItemToObject(root, "application", application);
+    
+    // ota
+    cJSON *ota = cJSON_CreateObject();
+    if (!ota) {
+        cJSON_Delete(root);
+        return -1;
+    }
+    cJSON_AddStringToObject(ota, "label", "ota_0");
+    cJSON_AddItemToObject(root, "ota", ota);
+    
+    // board
+    cJSON *board = cJSON_CreateObject();
+    if (!board) {
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    // 获取设备信息
+    const char *device_model = uapi_ln_get_device_model();
+    const char *board_type = device_model ? device_model : "bread-compact-wifi";
+    cJSON_AddStringToObject(board, "type", board_type);
+    
+    // 获取IP地址
+    const char *ip_addr = NULL;//ppp_lwip_get_ip_address();
+    if (ip_addr && strcmp(ip_addr, "0.0.0.0") != 0) {
+        cJSON_AddStringToObject(board, "ip", ip_addr);
+    } else {
+        cJSON_AddStringToObject(board, "ip", "0.0.0.0");
+    }
+    
+    // MAC地址 - 使用占位符,实际应从网络接口获取
+    cJSON_AddStringToObject(board, "mac", "00:00:00:00:00:00");
+    
+    cJSON_AddItemToObject(root, "board", board);
+    
+    // 转换为JSON字符串
+    char *json_str = cJSON_Print(root);
+    if (!json_str) {
+        printf("[LN_OTA] Failed to print JSON\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    printf("[LN_OTA] Device info JSON: %s\n", json_str);
+    
+    // 调用发送函数
+    int ret = ln_ota_send_device_info(target_url, json_str, (mqtt_credentials_t *)credentials);
+    
+    // 清理
+    free(json_str);
+    cJSON_Delete(root);
+    
+    return ret;
+}
+
+/**
+ * @brief 发送设备信息到服务器并解析回复,保存 MQTT 凭证
+ * @param url 服务器 URL
+ * @param device_info_json 设备信息的 JSON 字符串(如果为 NULL,将使用默认结构)
+ * @param credentials 输出的 MQTT 凭证(可以为 NULL,如果只需要保存到文件)
+ * @return 0 成功,-1 失败
+ */
+int ln_ota_send_device_info(const char *url, const char *device_info_json, mqtt_credentials_t *credentials)
+{
+    HttpClient client = {0};
+    HttpClientData client_data = {0};
+    int ret = -1;
+    
+    // 构建自定义请求头
+    char *header_buf = (char *)malloc(256);
+    if (!header_buf) {
+        printf("[LN_OTA] Failed to allocate header buffer\n");
+        return -1;
+    }
+    
+    memset(header_buf, 0, 256);
+    int hdr = snprintf(header_buf, 256,
+                       "Device-Id: %s\r\n",
+                       "8c:85:90:65:53:8d");
+    if (hdr <= 0 || hdr >= 256) {
+        printf("[LN_OTA] Failed to build header\n");
+        free(header_buf);
+        return -1;
+    }
+
+    // 设置自定义头(只包含Device-Id,Content-Type通过postContentType设置)
+    HttpClientSetCustomHeader(&client, header_buf);
+
+    // 准备HTTP缓冲区(自动分配headerBuf和responseBuf)
+    HTTPC_RESULT prep = HttpClientPrepare(&client_data, 2048, 4096);
+    if (prep != HTTP_SUCCESS) {
+        printf("[LN_OTA] HttpClientPrepare failed: %d\n", prep);
+        free(header_buf);
+        return -1;
+    }
+
+    // 设置POST数据和Content-Type(放在Prepare之后,避免被重置)
+    client_data.postBuf = (char *)device_info_json;
+    client_data.postBufLen = strlen(device_info_json);
+    client_data.postContentType = "application/json";
+    
+    printf("Sending POST request to: %s\n", url);
+    printf("POST data: %s\n", device_info_json);
+    printf("Custom header: %s\n", header_buf);
+    
+    ret = HttpClientPostRequest(&client, url, &client_data);
+    
+    if (ret == HTTP_SUCCESS && client.responseCode == 200) {
+        printf("HTTP request successful, response code: %d\n", client.responseCode);
+        printf("Response data: %s\n", client_data.responseBuf);
+        
+        // 提取 MQTT 凭证
+        mqtt_credentials_t cred = {0};
+        if (extract_mqtt_credentials(client_data.responseBuf, &cred) == 0) {
+            // 保存凭证到文件
+            if (save_mqtt_credentials(&cred) == 0) {
+                printf("MQTT credentials saved:\n");
+                printf("  endpoint: %s\n", cred.endpoint);
+                printf("  client_id: %s\n", cred.client_id);
+                printf("  username: %s\n", cred.username);
+                printf("  password: %s\n", cred.password);
+                printf("  publish_topic: %s\n", cred.publish_topic);
+                printf("  subscribe_topic: %s\n", cred.subscribe_topic);
+                
+                // 如果提供了输出参数,复制凭证
+                if (credentials) {
+                    memcpy(credentials, &cred, sizeof(mqtt_credentials_t));
+                }
+                
+                ret = 0;
+            } else {
+                printf("Failed to save MQTT credentials\n");
+                ret = -1;
+            }
+        } else {
+            printf("Failed to extract MQTT credentials from response\n");
+            ret = -1;
+        }
+    } else {
+        printf("HTTP request failed, response code: %d, error: %d\n", client.responseCode, ret);
+        if (client_data.responseBuf && client_data.responseBufLen > 0) {
+            printf("Response data: %s\n", client_data.responseBuf);
+        }
+        ret = -1;
+    }
+    
+    // 清理资源
+    HttpClientUnprepare(&client_data);
+    free(header_buf);
+    
+    return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_UDP.c b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_UDP.c
new file mode 100644 (file)
index 0000000..074c677
--- /dev/null
@@ -0,0 +1,1797 @@
+/*
+ * Copyright (c) Zhihui Technologies Co., Ltd. 2025-2025. All rights reserved.
+ */
+
+#include "ln_mqtt_api.h"
+#include "ln_api.h"
+#include "custom_utils.h"
+#include "cmsis_os2.h"
+#include "soc_osal.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+#include "lwip/sockets.h"
+#include "lwip/netdb.h"
+#include "lwip/inet.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/aes.h"
+#include <time.h>
+#include "opus_frame_to_pcm.h"
+#include "ai_media.h"
+
+/* 双流接口开关:定义 USE_DUAL_STREAM_INTERFACE 则使用 old_Start_AIVoice 双流接口,否则使用 MQTT_StartRecord */
+/* 可在 CMakeLists.txt 或编译选项中定义,例如:-DUSE_DUAL_STREAM_INTERFACE=1 */
+#ifndef USE_DUAL_STREAM_INTERFACE
+#define USE_DUAL_STREAM_INTERFACE 0
+#endif
+
+/* OGG 封装相关前向声明(不透明句柄,避免依赖 ogg.h) */
+/* OGG 上下文句柄(不透明指针,实际类型在 ai_media_service_mqtt.cpp 中定义) */
+typedef void* MqttOggContextHandle;
+
+/* OGG 封装接口声明(使用不透明句柄) */
+extern void* MqttOggGetContext(void);
+extern int32_t MqttOggEncapsulationInitHandle(MqttOggContextHandle oggCtxHandle, FILE *pfd, uint32_t sampleRate, uint32_t channelCount);
+extern int32_t MqttOggEncapsulationWriteHandle(MqttOggContextHandle oggCtxHandle, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos);
+extern int32_t MqttOggEncapsulationFinishHandle(MqttOggContextHandle oggCtxHandle, FILE *pfd);
+
+/* MQTT 播放接口声明 */
+typedef void (*MqttPlayerCallback)(int32_t event, void* userData);
+extern int32_t MQTT_PlayAudioFile(const char* filePath, MqttPlayerCallback callback, void* userData);
+
+/* UDP接收缓冲区大小 */
+#define UDP_RECV_BUFFER_SIZE 4096
+
+/* UDP数据包头部大小 */
+#define UDP_PACKET_HEADER_SIZE 16  // 1+1+2+4+4+4 = 16 bytes
+
+/* UDP数据包结构体 */
+typedef struct {
+    uint8_t type;               // 类型 (1 byte)
+    uint8_t flags;              // 标志 (1 byte)
+    uint16_t payload_len;       // 负载长度 (2 bytes, 网络字节序)
+    uint32_t ssrc;              // SSRC (4 bytes, 网络字节序)
+    uint32_t timestamp;         // 时间戳 (4 bytes, 网络字节序)
+    uint32_t sequence;          // 序列号 (4 bytes, 网络字节序)
+    uint8_t *payload;           // 加密负载数据指针
+    uint16_t payload_size;      // 负载数据大小
+} ln_udp_packet_t;
+
+/* UDP套接字全局变量 */
+static int g_udp_socket = -1;
+static volatile bool g_udp_thread_running = false;
+static uint32_t g_udp_thread_handle = 0;
+
+/* UDP数据包序列号和SSRC管理 */
+static uint32_t g_udp_ssrc = 0;          // SSRC标识
+static uint32_t g_udp_sequence = 0;      // 序列号(自动递增)
+
+/* 音频数据发送队列和线程 */
+#define AUDIO_SEND_QUEUE_SIZE 32  // 队列大小
+
+/* OGG 封装相关全局变量 */
+#define OGG_PACKETS_PER_FILE 50  // 每50个数据包打包成一个文件
+#define OGG_PACKET_CACHE_SIZE 32  // 数据包缓存大小(用于处理乱序)
+#define OGG_OPUS_ENCODE_HEADER_SIZE 8  // Opus 编码头大小(前8字节)
+#define ENABLE_OPUS_RAW_DEBUG 1  // 启用 Opus 原始数据保存调试(1=启用,0=禁用)
+
+static MqttOggContextHandle g_ogg_ctx_handle = NULL;  // OGG 上下文句柄(不透明指针)
+static FILE *g_ogg_file = NULL;      // 当前 OGG 文件句柄
+static uint32_t g_ogg_packet_count = 0; // 当前文件的数据包计数
+static uint32_t g_ogg_file_index = 0;   // 文件序号
+static bool g_ogg_initialized = false;  // OGG 上下文是否已初始化
+static char g_completed_ogg_filename[128] = {0};  // 已完成的 OGG 文件名(用于播放)
+
+/* Opus 原始数据调试相关全局变量 */
+static FILE *g_opus_debug_file = NULL;      // Opus 调试文件句柄
+static uint32_t g_opus_debug_packet_count = 0; // Opus 调试文件的数据包计数
+static uint32_t g_opus_debug_file_index = 0;   // Opus 调试文件序号
+#define OPUS_DEBUG_PCM_BUF_SAMPLES 5760   // 单帧解码 PCM 缓冲(120ms@48kHz)
+static short g_opus_debug_pcm_buf[OPUS_DEBUG_PCM_BUF_SAMPLES];
+static FILE *g_opus_debug_pcm_file = NULL;    // 解码 PCM 测试输出文件(追加)
+
+/* 数据包缓存结构(用于处理乱序接收) */
+typedef struct {
+    uint32_t sequence;      // 序列号
+    uint8_t *data;          // 数据指针(动态分配)
+    uint32_t data_size;     // 数据大小
+    bool valid;             // 是否有效
+} ogg_packet_cache_t;
+
+static ogg_packet_cache_t g_ogg_packet_cache[OGG_PACKET_CACHE_SIZE] = {0};  // 数据包缓存
+static uint32_t g_ogg_expected_sequence = 0;  // 期望的下一个序列号(0表示未初始化)
+static uint32_t g_ogg_out_of_order_count = 0;  // 连续错序计数器(用于检测丢包)
+#define OGG_MAX_OUT_OF_ORDER_COUNT 5  // 最大连续错序次数,超过后跳过一包
+#define AUDIO_SEND_MAX_DATA_SIZE 0x800  // 最大音频数据大小(与 LN_MQTT_RECORD_MAX_FRAME 一致)
+
+/* 音频数据消息结构体 */
+typedef struct {
+    uint8_t *data;    // 音频数据指针(动态分配)
+    uint32_t size;    // 数据大小
+} audio_send_msg_t;
+
+static unsigned long g_audio_send_queue = 0xFFFFFFFF;  // 消息队列句柄
+static volatile bool g_audio_send_thread_running = false;
+static uint32_t g_audio_send_thread_handle = 0;
+
+/* 前向声明 */
+static void ln_udp_recv_thread(void *arg);
+static int ln_udp_process_received_data(const uint8_t *data, uint16_t data_len);
+int ln_udp_unpack_packet(const uint8_t *data, uint16_t data_len, ln_udp_packet_t *packet);
+void ln_udp_free_packet(ln_udp_packet_t *packet);
+void ln_udp_close_socket(void);
+int ln_udp_decrypt_audio(const char *key_hex, const char *base_nonce_hex,
+                         uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+                         const uint8_t *encrypted_data, uint16_t encrypted_len, uint8_t *decrypted_data);
+static void ln_udp_audio_send_thread(void *arg);
+static void create_audio_send_queue(void);
+/* OGG 封装相关函数声明 */
+static int ln_udp_ogg_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_ogg_cache_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static int ln_udp_ogg_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_ogg_flush_cache(void);
+static void ln_udp_ogg_complete_current_file(void);
+static int ln_udp_ogg_create_new_file(void);
+
+#if USE_DUAL_STREAM_INTERFACE
+/* 双流接口相关函数声明 */
+static int ln_udp_dual_stream_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static int ln_udp_dual_stream_decode_and_send(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_dual_stream_flush_cache(void);
+#endif /* USE_DUAL_STREAM_INTERFACE */
+/* Opus 原始数据调试相关函数声明 */
+static int ln_udp_opus_debug_create_new_file(void);
+static void ln_udp_opus_debug_complete_current_file(void);
+static int ln_udp_opus_debug_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+/* Opus 数据包解析函数声明 */
+static int ln_udp_parse_opus_packet(const uint8_t *data, uint32_t data_size, 
+                                    const uint8_t **opus_data, uint32_t *opus_data_size);
+
+
+
+/**
+ * @brief 处理接收到的UDP数据(解包、解密)
+ * @param data 原始接收数据
+ * @param data_len 数据长度
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_process_received_data(const uint8_t *data, uint16_t data_len)
+{
+    ln_udp_packet_t packet;
+    memset(&packet, 0, sizeof(packet));
+    
+    // 1. 解包数据包
+    if (ln_udp_unpack_packet(data, data_len, &packet) != 0) {
+        printf("[LN_UDP] Failed to unpack packet\n");
+        return -1;
+    }
+    
+    printf("[LN_UDP] Packet unpacked: type=%d, flags=%d, ssrc=%u, timestamp=%u, sequence=%u, payload_len=%d\n",
+           packet.type, packet.flags, packet.ssrc, packet.timestamp, packet.sequence, packet.payload_len);
+    
+    // 2. 获取UDP信息(用于解密)
+    ln_mqtt_udp_info_t udp_info;
+    if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+        printf("[LN_UDP] UDP info not available for decryption\n");
+        ln_udp_free_packet(&packet);
+        return -1;
+    }
+    
+    // 3. 解密负载数据
+    if (packet.payload_len > 0 && packet.payload) {
+        // 分配解密数据缓冲区
+        uint8_t *decrypted_data = (uint8_t *)malloc(packet.payload_len);
+        if (!decrypted_data) {
+            printf("[LN_UDP] Failed to allocate memory for decrypted data\n");
+            ln_udp_free_packet(&packet);
+            return -1;
+        }
+        
+        // 执行解密(nonce在函数内部构造)
+        if (ln_udp_decrypt_audio(udp_info.key, udp_info.nonce, packet.payload_len, 
+                                 packet.timestamp, packet.sequence,
+                                 packet.payload, packet.payload_len, decrypted_data) != 0) {
+            printf("[LN_UDP] Failed to decrypt payload data\n");
+            free(decrypted_data);
+            ln_udp_free_packet(&packet);
+            return -1;
+        }
+        printf("decrypted_data: ");
+
+        printf("\n");
+        
+        printf("[LN_UDP] Payload decrypted successfully, size=%d bytes\n", packet.payload_len);
+        
+        printf("packet.sequence: %u\n", packet.sequence);
+
+#if USE_DUAL_STREAM_INTERFACE
+        // 使用双流接口时,不进行 OGG 封装,但需要保持包顺序处理
+        // 注意:decrypted_data 的所有权会转移给处理函数,不需要在这里释放
+        if (ln_udp_dual_stream_handle_packet(packet.sequence, decrypted_data, packet.payload_len) != 0) {
+            printf("[LN_UDP] Failed to handle dual stream packet (sequence=%u)\n", packet.sequence);
+            free(decrypted_data);  // 处理失败时才释放
+        }
+#else
+        // OGG 封装处理:使用独立函数处理,支持乱序数据包缓存和排序
+        // 注意:decrypted_data 的所有权会转移给处理函数,不需要在这里释放
+        if (ln_udp_ogg_handle_packet(packet.sequence, decrypted_data, packet.payload_len) != 0) {
+            printf("[LN_UDP] Failed to handle OGG packet (sequence=%u)\n", packet.sequence);
+            free(decrypted_data);  // 处理失败时才释放
+        }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+    } else {
+        printf("[LN_UDP] Packet has no payload data\n");
+    }
+    
+    // 4. 释放数据包
+    ln_udp_free_packet(&packet);
+    
+    return 0;
+}
+
+/**
+ * @brief 解包UDP数据包
+ * @param data 原始数据缓冲区
+ * @param data_len 数据长度
+ * @param packet 输出的数据包结构体指针(payload字段需要外部释放)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_unpack_packet(const uint8_t *data, uint16_t data_len, ln_udp_packet_t *packet)
+{
+    if (!data || !packet || data_len < UDP_PACKET_HEADER_SIZE) {
+        printf("[LN_UDP] Invalid parameters or data too short for unpack\n");
+        return -1;
+    }
+    
+    memset(packet, 0, sizeof(ln_udp_packet_t));
+    
+    // 解析头部字段(网络字节序)
+    const uint8_t *ptr = data;
+    packet->type = ptr[0];
+    packet->flags = ptr[1];
+    packet->payload_len = lwip_ntohs(*(uint16_t *)(ptr + 2));
+    packet->ssrc = lwip_ntohl(*(uint32_t *)(ptr + 4));
+    packet->timestamp = lwip_ntohl(*(uint32_t *)(ptr + 8));
+    packet->sequence = lwip_ntohl(*(uint32_t *)(ptr + 12));
+    
+    // 验证负载长度
+    uint16_t expected_len = UDP_PACKET_HEADER_SIZE + packet->payload_len;
+    if (data_len < expected_len) {
+        printf("[LN_UDP] Data length mismatch: expected %d, got %d\n", expected_len, data_len);
+        return -1;
+    }
+    
+    // 分配并复制负载数据
+    if (packet->payload_len > 0) {
+        packet->payload = (uint8_t *)malloc(packet->payload_len);
+        if (!packet->payload) {
+            printf("[LN_UDP] Failed to allocate memory for payload\n");
+            return -1;
+        }
+        memcpy(packet->payload, ptr + UDP_PACKET_HEADER_SIZE, packet->payload_len);
+        packet->payload_size = packet->payload_len;
+    } else {
+        packet->payload = NULL;
+        packet->payload_size = 0;
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 封包UDP数据包
+ * @param packet 数据包结构体指针
+ * @param buffer 输出缓冲区指针(由调用者分配)
+ * @param buffer_size 缓冲区大小
+ * @param out_len 输出的实际数据长度
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_pack_packet(const ln_udp_packet_t *packet, uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len)
+{
+    if (!packet || !buffer || !out_len) {
+        printf("[LN_UDP] Invalid parameters for pack\n");
+        return -1;
+    }
+    
+    // 计算所需缓冲区大小
+    uint16_t total_len = UDP_PACKET_HEADER_SIZE + packet->payload_len;
+    if (buffer_size < total_len) {
+        printf("[LN_UDP] Buffer too small: need %d, have %d\n", total_len, buffer_size);
+        return -1;
+    }
+    
+    // 打包头部字段(转换为网络字节序)
+    uint8_t *ptr = buffer;
+    ptr[0] = packet->type;
+    ptr[1] = packet->flags;
+    *(uint16_t *)(ptr + 2) = lwip_htons(packet->payload_len);
+    *(uint32_t *)(ptr + 4) = lwip_htonl(packet->ssrc);
+    *(uint32_t *)(ptr + 8) = lwip_htonl(packet->timestamp);
+    *(uint32_t *)(ptr + 12) = lwip_htonl(packet->sequence);
+    
+    // 复制负载数据
+    if (packet->payload_len > 0 && packet->payload) {
+        memcpy(ptr + UDP_PACKET_HEADER_SIZE, packet->payload, packet->payload_len);
+    }
+    
+    *out_len = total_len;
+    return 0;
+}
+
+/**
+ * @brief 释放数据包结构体的负载数据
+ * @param packet 数据包结构体指针
+ */
+void ln_udp_free_packet(ln_udp_packet_t *packet)
+{
+    if (packet && packet->payload) {
+        free(packet->payload);
+        packet->payload = NULL;
+        packet->payload_size = 0;
+    }
+}
+
+// ==================== OGG 封装处理函数(支持乱序数据包缓存和排序)====================
+
+/**
+ * @brief 清空数据包缓存
+ */
+static void ln_udp_ogg_clear_cache(void)
+{
+    for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+        if (g_ogg_packet_cache[i].valid && g_ogg_packet_cache[i].data != NULL) {
+            free(g_ogg_packet_cache[i].data);
+            g_ogg_packet_cache[i].data = NULL;
+        }
+        g_ogg_packet_cache[i].valid = false;
+        g_ogg_packet_cache[i].sequence = 0;
+        g_ogg_packet_cache[i].data_size = 0;
+    }
+}
+
+/**
+ * @brief 将数据包缓存(用于处理乱序接收)
+ * @param sequence 序列号
+ * @param data 数据指针(会被复制,调用者可以释放)
+ * @param data_size 数据大小
+ */
+static void ln_udp_ogg_cache_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+    // 查找空闲的缓存槽
+    int empty_slot = -1;
+    for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+        if (!g_ogg_packet_cache[i].valid) {
+            empty_slot = i;
+            break;
+        }
+    }
+    
+    if (empty_slot < 0) {
+        printf("[LN_UDP] OGG cache full, dropping packet sequence=%u\n", sequence);
+        return;
+    }
+    
+    // 分配内存并复制数据
+    uint8_t *cached_data = (uint8_t *)malloc(data_size);
+    if (cached_data == NULL) {
+        printf("[LN_UDP] Failed to allocate memory for cached packet sequence=%u\n", sequence);
+        return;
+    }
+    
+    memcpy(cached_data, data, data_size);
+    
+    // 保存到缓存
+    g_ogg_packet_cache[empty_slot].sequence = sequence;
+    g_ogg_packet_cache[empty_slot].data = cached_data;
+    g_ogg_packet_cache[empty_slot].data_size = data_size;
+    g_ogg_packet_cache[empty_slot].valid = true;
+    
+    printf("[LN_UDP] Cached packet sequence=%u (slot=%d)\n", sequence, empty_slot);
+}
+
+/**
+ * @brief 创建新的 Opus 调试文件(直接保存 Opus 原始数据)
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_opus_debug_create_new_file(void)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+    // 创建新文件(使用时间戳和序号命名)
+    time_t now = time(NULL);
+    struct tm *tm_info = localtime(&now);
+    char filename[128];
+    snprintf(filename, sizeof(filename), "/user/udp_opus_raw_%04d%02d%02d_%02d%02d%02d_%03u.opus",
+             tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+             tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, g_opus_debug_file_index);
+    
+    g_opus_debug_file = fopen(filename, "wb");
+    if (g_opus_debug_file == NULL) {
+        printf("[LN_UDP] Failed to open Opus debug file: %s\n", filename);
+        return -1;
+    }
+    
+    g_opus_debug_packet_count = 0;
+    g_opus_debug_file_index++;
+    printf("[LN_UDP] Created new Opus debug file: %s (index: %u)\n", filename, g_opus_debug_file_index - 1);
+    
+    return 0;
+#else
+    return -1;
+#endif
+}
+
+/**
+ * @brief 完成当前 Opus 调试文件
+ */
+static void ln_udp_opus_debug_complete_current_file(void)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+    if (g_opus_debug_file == NULL) {
+        return;
+    }
+    
+    fclose(g_opus_debug_file);
+    g_opus_debug_file = NULL;
+    g_opus_debug_packet_count = 0;
+    printf("[LN_UDP] Completed Opus debug file #%u\n", g_opus_debug_file_index - 1);
+#endif
+}
+
+/**
+ * @brief 解析 Opus 数据包,找到实际 Opus 编码数据的起始位置和大小
+ * @param data 完整的 Opus 数据包(包含 TOC 字节和可能的帧长度表)
+ * @param data_size 数据包总大小
+ * @param opus_data 输出的实际 Opus 数据起始指针
+ * @param opus_data_size 输出的实际 Opus 数据大小
+ * @return 0 成功,-1 失败
+ * @note 根据 RFC 6716 Opus 编码标准解析
+ */
+static int ln_udp_parse_opus_packet(const uint8_t *data, uint32_t data_size, 
+                                    const uint8_t **opus_data, uint32_t *opus_data_size)
+{
+    if (!data || data_size == 0 || !opus_data || !opus_data_size) {
+        printf("[LN_UDP] Invalid parameters for Opus packet parsing\n");
+        return -1;
+    }
+    
+    // 至少需要 TOC 字节
+    if (data_size < 1) {
+        printf("[LN_UDP] Opus packet too small (size=%u)\n", data_size);
+        return -1;
+    }
+    
+    const uint8_t *ptr = data;
+    uint32_t remaining = data_size;
+    
+    // 1. 读取 TOC 字节
+    uint8_t toc = ptr[0];
+    ptr++;
+    remaining--;
+    
+    // 2. 解析帧计数编码(bit 3-7)
+    uint8_t frame_count_code = (toc >> 3) & 0x1F;  // bit 3-7
+    uint8_t frame_count = 0;
+    uint32_t header_size = 1;  // TOC 字节
+    
+    // 3. 判断是单帧还是多帧
+    if (frame_count_code < 16) {
+        // 单帧:帧计数 = 编码值(0表示1帧,1-15表示对应帧数)
+        if (frame_count_code == 0) {
+            frame_count = 1;  // 编码值0表示单帧
+        } else {
+            frame_count = frame_count_code;
+        }
+    } else {
+        // 多帧:需要读取帧计数字节
+        if (remaining < 1) {
+            printf("[LN_UDP] Opus packet too small for frame count byte\n");
+            return -1;
+        }
+        frame_count = frame_count_code - 16 + 1 + ptr[0];
+        ptr++;
+        remaining--;
+        header_size++;
+    }
+    
+    // 4. 如果是多帧,需要读取帧长度表(但不跳过数据)
+    if (frame_count > 1) {
+        // 多帧数据包需要帧长度表
+        // 每个帧长度使用可变长度编码(1-2字节)
+        // 如果长度 < 252,使用1字节;否则使用2字节(0xFC + 实际长度)
+        // 注意:我们只读取长度值,不跳过帧数据,因为所有帧数据是连续存储的
+        for (uint8_t i = 0; i < frame_count - 1; i++) {
+            if (remaining < 1) {
+                printf("[LN_UDP] Opus packet too small for frame length table\n");
+                return -1;
+            }
+            
+            if (ptr[0] < 252) {
+                // 1字节编码
+                ptr++;
+                remaining--;
+                header_size++;
+            } else {
+                // 2字节编码:0xFC + 实际长度(大端序)
+                if (remaining < 2) {
+                    printf("[LN_UDP] Opus packet too small for 2-byte frame length\n");
+                    return -1;
+                }
+                ptr += 2;
+                remaining -= 2;
+                header_size += 2;
+            }
+        }
+    }
+    
+    // 5. 现在 header_size 包含了所有头部信息(TOC + 帧计数 + 帧长度表)
+    // 从 header_size 之后的所有数据都是 Opus 编码数据(包含所有帧的数据)
+    if (header_size >= data_size) {
+        printf("[LN_UDP] Opus header size (%u) >= total size (%u)\n", header_size, data_size);
+        return -1;
+    }
+    
+    *opus_data = data + header_size;
+    *opus_data_size = data_size - header_size;
+    
+    printf("[LN_UDP] Opus parsed: frame_count=%d, header_size=%u, opus_data_size=%u\n", 
+           frame_count, header_size, *opus_data_size);
+    
+    return 0;
+}
+
+/**
+ * @brief 写入 Opus 原始数据到调试文件(不进行 OGG 封装)
+ * @param sequence 序列号
+ * @param data 数据指针(包含 Opus TOC 字节和可能的帧长度表)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_opus_debug_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+    // 检查是否需要创建新文件
+    if (g_opus_debug_file == NULL || g_opus_debug_packet_count >= OGG_PACKETS_PER_FILE) {
+        // 完成当前文件
+        if (g_opus_debug_file != NULL) {
+            ln_udp_opus_debug_complete_current_file();
+        }
+        
+        // 创建新文件
+        if (ln_udp_opus_debug_create_new_file() != 0) {
+            return -1;
+        }
+    }
+    printf("opus debug data: ");
+    for (int i = 0; i < data_size; i++) {
+        printf("%02X ", data[i]);
+    }
+    printf("\n");
+    
+    // 解析 Opus 数据包(用于验证和日志输出,但不影响保存)
+    const uint8_t *opus_data = NULL;
+    uint32_t opus_data_size = 0;
+    int parse_ret = ln_udp_parse_opus_packet(data, data_size, &opus_data, &opus_data_size);
+    if (parse_ret == 0) {
+        printf("[LN_UDP] Opus debug: Parsed packet sequence=%u, total_size=%u, opus_data_size=%u\n", 
+               sequence, data_size, opus_data_size);
+    } else {
+        printf("[LN_UDP] Opus debug: Parse warning (sequence=%u, size=%u), but saving raw data anyway\n", 
+               sequence, data_size);
+    }
+
+    /* 调用 opus 解码接口测试:完整包 data/data_size 送入解码 */
+    {
+        int pcm_samples = 0;
+        int dec_ret = opus_frame_to_pcm_decode_packet(
+            data, (int)data_size,
+            16000, 1,
+            g_opus_debug_pcm_buf, OPUS_DEBUG_PCM_BUF_SAMPLES,
+            &pcm_samples);
+        if (dec_ret == 0) {
+            printf("[LN_UDP] Opus decode test OK sequence=%u pcm_samples=%d\n", sequence, pcm_samples);
+            if (g_opus_debug_pcm_file == NULL) {
+                g_opus_debug_pcm_file = fopen("user/udp_opus_debug.pcm", "ab");
+                if (g_opus_debug_pcm_file != NULL) {
+                    printf("[LN_UDP] Opus decode PCM output: udp_opus_debug.pcm (append)\n");
+                }
+            }
+            if (g_opus_debug_pcm_file != NULL && pcm_samples > 0) {
+                size_t n = fwrite(g_opus_debug_pcm_buf, sizeof(short), (size_t)pcm_samples, g_opus_debug_pcm_file);
+                if (n != (size_t)pcm_samples) {
+                    printf("[LN_UDP] Opus decode PCM write short: %zu/%d\n", n, pcm_samples);
+                }
+                fflush(g_opus_debug_pcm_file);
+            }
+            fclose(g_opus_debug_pcm_file);
+            g_opus_debug_pcm_file = NULL;
+        } else {
+            printf("[LN_UDP] Opus decode test FAIL sequence=%u\n", sequence);
+        }
+    }
+    
+    // 保存完整的原始数据(包含 TOC 字节和帧长度表)
+    size_t written = fwrite(data, 1, data_size, g_opus_debug_file);
+    if (written != data_size) {
+        printf("[LN_UDP] Opus debug: Failed to write data (sequence=%u, written=%zu, expected=%u)\n", 
+               sequence, written, data_size);
+        return -1;
+    }
+    
+    fflush(g_opus_debug_file);  // 立即刷新到文件
+    
+    g_opus_debug_packet_count++;
+    printf("[LN_UDP] Opus debug: Written packet sequence=%u (%u/%u, raw_size=%u bytes)\n", 
+           sequence, g_opus_debug_packet_count, OGG_PACKETS_PER_FILE, data_size);
+    
+    return 0;
+#else
+    return 0;  // 未启用时直接返回成功
+#endif
+}
+
+/**
+ * @brief 写入数据包到 OGG 文件
+ * @param sequence 序列号
+ * @param data 数据指针
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_ogg_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+    // 调试模式:同时保存 Opus 原始数据
+#if ENABLE_OPUS_RAW_DEBUG
+    ln_udp_opus_debug_write_packet(sequence, data, data_size);
+#endif
+    
+    // 检查是否需要创建新文件
+    if (!g_ogg_initialized || g_ogg_packet_count >= OGG_PACKETS_PER_FILE) {
+        // 完成当前文件
+        if (g_ogg_initialized) {
+            ln_udp_ogg_complete_current_file();
+        }
+        
+        // 创建新文件
+        if (ln_udp_ogg_create_new_file() != 0) {
+            return -1;
+        }
+    }
+    
+    // 写入数据包
+    if (g_ogg_ctx_handle == NULL) {
+        printf("[LN_UDP] OGG context handle is null\n");
+        return -1;
+    }
+    if (MqttOggEncapsulationWriteHandle(g_ogg_ctx_handle, data, data_size, g_ogg_file, false) != 0) {
+        printf("[LN_UDP] Failed to write OGG data (sequence=%u)\n", sequence);
+        return -1;
+    }
+    
+    g_ogg_packet_count++;
+    printf("[LN_UDP] Written packet sequence=%u (%u/%u to OGG file)\n", 
+           sequence, g_ogg_packet_count, OGG_PACKETS_PER_FILE);
+    
+    return 0;
+}
+
+/**
+ * @brief 刷新缓存:尝试按顺序写入缓存中的数据包
+ */
+static void ln_udp_ogg_flush_cache(void)
+{
+    bool found = true;
+    while (found) {
+        found = false;
+        // 查找期望的下一个序列号
+        for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+            if (g_ogg_packet_cache[i].valid && 
+                g_ogg_packet_cache[i].sequence == g_ogg_expected_sequence) {
+                // 找到期望的包,写入
+                if (ln_udp_ogg_write_packet(g_ogg_packet_cache[i].sequence,
+                                            g_ogg_packet_cache[i].data,
+                                            g_ogg_packet_cache[i].data_size) == 0) {
+                    // 更新期望的序列号
+                    g_ogg_expected_sequence++;
+                    // 释放缓存
+                    free(g_ogg_packet_cache[i].data);
+                    g_ogg_packet_cache[i].data = NULL;
+                    g_ogg_packet_cache[i].valid = false;
+                    g_ogg_packet_cache[i].sequence = 0;
+                    g_ogg_packet_cache[i].data_size = 0;
+                    found = true;
+                    printf("[LN_UDP] Flushed cached packet sequence=%u\n", 
+                           g_ogg_expected_sequence - 1);
+                    break;  // 重新开始查找
+                } else {
+                    // 写入失败,保留在缓存中
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * @brief 完成当前 OGG 文件并播放
+ */
+static void ln_udp_ogg_complete_current_file(void)
+{
+    if (!g_ogg_initialized || g_ogg_file == NULL) {
+        return;
+    }
+    
+    // 写入结束标志并完成封装
+    if (g_ogg_ctx_handle != NULL) {
+        uint8_t empty_data[8] = {0};  // 至少需要8字节的编码头
+        MqttOggEncapsulationWriteHandle(g_ogg_ctx_handle, empty_data, 8, g_ogg_file, true);
+        MqttOggEncapsulationFinishHandle(g_ogg_ctx_handle, g_ogg_file);
+    }
+    fclose(g_ogg_file);
+    g_ogg_file = NULL;
+    g_ogg_initialized = false;
+    
+    printf("[LN_UDP] Completed OGG file #%u with %u packets: %s\n", 
+           g_ogg_file_index - 1, g_ogg_packet_count, g_completed_ogg_filename);
+    
+    // 使用 MQTT 播放接口播放完成的文件
+    if (g_completed_ogg_filename[0] != '\0') {
+        int32_t play_ret = MQTT_PlayAudioFile(g_completed_ogg_filename, NULL, NULL);
+        if (play_ret == 0) {
+            printf("[LN_UDP] Started playing OGG file: %s\n", g_completed_ogg_filename);
+        } else {
+            printf("[LN_UDP] Failed to play OGG file: %s (ret=%d)\n", 
+                   g_completed_ogg_filename, play_ret);
+        }
+        g_completed_ogg_filename[0] = '\0';
+    }
+}
+
+/**
+ * @brief 创建新的 OGG 文件
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_ogg_create_new_file(void)
+{
+    // 创建新文件(使用时间戳和序号命名)
+    time_t now = time(NULL);
+    struct tm *tm_info = localtime(&now);
+    char filename[128];
+    snprintf(filename, sizeof(filename), "/user/udp_audio_%04d%02d%02d_%02d%02d%02d_%03u.ogg",
+             tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+             tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, g_ogg_file_index);
+    
+    // 保存文件名(用于后续播放)
+    strncpy(g_completed_ogg_filename, filename, sizeof(g_completed_ogg_filename) - 1);
+    g_completed_ogg_filename[sizeof(g_completed_ogg_filename) - 1] = '\0';
+    
+    g_ogg_file = fopen(filename, "wb");
+    if (g_ogg_file == NULL) {
+        printf("[LN_UDP] Failed to open OGG file: %s\n", filename);
+        g_completed_ogg_filename[0] = '\0';
+        return -1;
+    }
+    
+    // 获取 OGG 上下文句柄(如果尚未获取)
+    if (g_ogg_ctx_handle == NULL) {
+        g_ogg_ctx_handle = MqttOggGetContext();
+        if (g_ogg_ctx_handle == NULL) {
+            printf("[LN_UDP] Failed to get OGG context handle\n");
+            fclose(g_ogg_file);
+            g_ogg_file = NULL;
+            g_completed_ogg_filename[0] = '\0';
+            return -1;
+        }
+    }
+    
+    // 初始化 OGG 上下文
+    if (MqttOggEncapsulationInitHandle(g_ogg_ctx_handle, g_ogg_file, 16000, 1) != 0) {
+        printf("[LN_UDP] Failed to initialize OGG context\n");
+        fclose(g_ogg_file);
+        g_ogg_file = NULL;
+        g_completed_ogg_filename[0] = '\0';
+        return -1;
+    }
+    
+    g_ogg_initialized = true;
+    g_ogg_packet_count = 0;
+    g_ogg_file_index++;
+    printf("[LN_UDP] Created new OGG file: %s (index: %u)\n", filename, g_ogg_file_index - 1);
+    
+    return 0;
+}
+
+/**
+ * @brief 处理 OGG 数据包(支持乱序接收和缓存)
+ * @param sequence 数据包序列号
+ * @param data 解密后的数据(所有权转移,函数内部负责释放)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ * @note 此函数会接管 data 的所有权,调用者不应再释放 data
+ */
+static int ln_udp_ogg_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+    // 初始化期望序列号(首次接收)
+    if (g_ogg_expected_sequence == 0) {
+        g_ogg_expected_sequence = sequence;
+        g_ogg_out_of_order_count = 0;  // 重置错序计数器
+        printf("[LN_UDP] Initialized expected sequence to %u\n", sequence);
+    }
+    
+    // 检查是否是期望的下一个包
+    if (sequence == g_ogg_expected_sequence) {
+        // 是期望的包,直接写入
+        if (ln_udp_ogg_write_packet(sequence, data, data_size) == 0) {
+            g_ogg_expected_sequence++;
+            g_ogg_out_of_order_count = 0;  // 重置错序计数器(收到期望的包)
+            free((void *)data);  // 释放数据(所有权已转移)
+            
+            // 尝试刷新缓存中的后续包
+            ln_udp_ogg_flush_cache();
+            return 0;
+        } else {
+            // 写入失败,缓存这个包
+            ln_udp_ogg_cache_packet(sequence, data, data_size);
+            free((void *)data);
+            return -1;
+        }
+    } else if (sequence > g_ogg_expected_sequence) {
+        // 是未来的包,缓存起来
+        g_ogg_out_of_order_count++;  // 增加错序计数器
+        printf("[LN_UDP] Received future packet sequence=%u (expected=%u), caching (out_of_order_count=%u)\n", 
+               sequence, g_ogg_expected_sequence, g_ogg_out_of_order_count);
+        
+        // 如果连续错序超过阈值,跳过期望的序列号(避免丢包时一直无法正常输出)
+        if (g_ogg_out_of_order_count > OGG_MAX_OUT_OF_ORDER_COUNT) {
+            uint32_t old_expected = g_ogg_expected_sequence;
+            printf("[LN_UDP] Out of order count exceeded %d, skipping sequence %u\n", 
+                   OGG_MAX_OUT_OF_ORDER_COUNT, g_ogg_expected_sequence);
+            
+            // 1. 先将期望序号往后加一(跳过丢失的包)
+            g_ogg_expected_sequence++;
+            g_ogg_out_of_order_count = 0;  // 重置计数器
+            
+            // 2. 处理缓存中的包(尝试写入缓存中所有能写入的连续包)
+            ln_udp_ogg_flush_cache();
+            
+            // 3. 再尝试写入当前包
+            if (sequence == g_ogg_expected_sequence) {
+                // 当前包正好是期望的包,直接写入
+                if (ln_udp_ogg_write_packet(sequence, data, data_size) == 0) {
+                    g_ogg_expected_sequence++;
+                    free((void *)data);
+                    // 继续刷新缓存中的后续包
+                    ln_udp_ogg_flush_cache();
+                    printf("[LN_UDP] Successfully wrote skipped packet sequence=%u (old_expected=%u)\n", 
+                           sequence, old_expected);
+                    return 0;
+                } else {
+                    // 写入失败,缓存这个包
+                    ln_udp_ogg_cache_packet(sequence, data, data_size);
+                    free((void *)data);
+                    return -1;
+                }
+            } else if (sequence > g_ogg_expected_sequence) {
+                // 当前包仍然是未来的包,缓存起来
+                printf("[LN_UDP] Current packet sequence=%u still ahead of expected=%u after skip, caching\n", 
+                       sequence, g_ogg_expected_sequence);
+                ln_udp_ogg_cache_packet(sequence, data, data_size);
+                free((void *)data);
+                return 0;
+            } else {
+                // 当前包已经是过去的包(在刷新缓存时已处理),丢弃
+                printf("[LN_UDP] Current packet sequence=%u is now old (expected=%u), dropping\n", 
+                       sequence, g_ogg_expected_sequence);
+                free((void *)data);
+                return 0;
+            }
+        } else {
+            // 正常缓存未来包
+            ln_udp_ogg_cache_packet(sequence, data, data_size);
+            free((void *)data);
+            return 0;
+        }
+    } else {
+        // 是过去的包(重复或乱序),丢弃
+        printf("[LN_UDP] Received old/duplicate packet sequence=%u (expected=%u), dropping\n", 
+               sequence, g_ogg_expected_sequence);
+        free((void *)data);
+        return 0;
+    }
+}
+
+#if USE_DUAL_STREAM_INTERFACE
+// ==================== 双流接口处理函数(支持乱序数据包缓存和排序)====================
+
+/**
+ * @brief 解码 Opus 数据包并送入 AI_SendAudioDataToQueue
+ * @param sequence 序列号
+ * @param data 数据指针
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_dual_stream_decode_and_send(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+    int pcm_samples = 0;
+    int dec_ret = opus_frame_to_pcm_decode_packet(
+        data, (int)data_size,
+        16000, 1,
+        g_opus_debug_pcm_buf, OPUS_DEBUG_PCM_BUF_SAMPLES,
+        &pcm_samples);
+    
+    if (dec_ret == 0 && pcm_samples > 0) {
+        // 解码成功,将 PCM 数据送入 AI_SendAudioDataToQueue
+        uint32_t pcm_data_size = (uint32_t)(pcm_samples * sizeof(short));
+        int32_t send_ret = AI_SendAudioDataToQueue((const uint8_t *)g_opus_debug_pcm_buf, pcm_data_size);
+        if (send_ret == 0) {
+            printf("[LN_UDP] Dual stream: Decoded and sent to queue: sequence=%u, pcm_samples=%d\n", 
+                   sequence, pcm_samples);
+            return 0;
+        } else {
+            printf("[LN_UDP] Dual stream: Failed to send decoded PCM to queue: sequence=%u, ret=%d\n", 
+                   sequence, (int)send_ret);
+            return -1;
+        }
+    } else {
+        printf("[LN_UDP] Dual stream: Opus decode failed: sequence=%u, ret=%d\n", 
+               sequence, dec_ret);
+        return -1;
+    }
+}
+
+/**
+ * @brief 刷新双流数据包缓存(按顺序处理缓存中的包)
+ */
+static void ln_udp_dual_stream_flush_cache(void)
+{
+    bool found = true;
+    while (found) {
+        found = false;
+        // 查找期望序列号的包
+        for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+            if (g_ogg_packet_cache[i].valid && 
+                g_ogg_packet_cache[i].sequence == g_ogg_expected_sequence) {
+                // 找到期望的包,解码并发送
+                if (ln_udp_dual_stream_decode_and_send(g_ogg_packet_cache[i].sequence,
+                                                        g_ogg_packet_cache[i].data,
+                                                        g_ogg_packet_cache[i].data_size) == 0) {
+                    g_ogg_expected_sequence++;
+                    // 释放缓存数据
+                    free(g_ogg_packet_cache[i].data);
+                    g_ogg_packet_cache[i].data = NULL;
+                    g_ogg_packet_cache[i].valid = false;
+                    g_ogg_packet_cache[i].sequence = 0;
+                    g_ogg_packet_cache[i].data_size = 0;
+                    found = true;  // 继续查找下一个期望的包
+                    printf("[LN_UDP] Dual stream: Flushed cached packet sequence=%u\n", 
+                           g_ogg_expected_sequence - 1);
+                    break;  // 重新开始查找
+                } else {
+                    // 解码失败,停止刷新
+                    found = false;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * @brief 处理双流数据包(支持乱序接收和缓存)
+ * @param sequence 数据包序列号
+ * @param data 解密后的数据(所有权转移,函数内部负责释放)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ * @note 此函数会接管 data 的所有权,调用者不应再释放 data
+ */
+static int ln_udp_dual_stream_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+    // 初始化期望序列号(首次接收)
+    if (g_ogg_expected_sequence == 0) {
+        g_ogg_expected_sequence = sequence;
+        g_ogg_out_of_order_count = 0;  // 重置错序计数器
+        printf("[LN_UDP] Dual stream: Initialized expected sequence to %u\n", sequence);
+    }
+    
+    // 检查是否是期望的下一个包
+    if (sequence == g_ogg_expected_sequence) {
+        // 是期望的包,直接解码并发送
+        if (ln_udp_dual_stream_decode_and_send(sequence, data, data_size) == 0) {
+            g_ogg_expected_sequence++;
+            g_ogg_out_of_order_count = 0;  // 重置错序计数器(收到期望的包)
+            free((void *)data);  // 释放数据(所有权已转移)
+            
+            // 尝试刷新缓存中的后续包
+            ln_udp_dual_stream_flush_cache();
+            return 0;
+        } else {
+            // 解码失败,缓存这个包
+            ln_udp_ogg_cache_packet(sequence, data, data_size);
+            free((void *)data);
+            return -1;
+        }
+    } else if (sequence > g_ogg_expected_sequence) {
+        // 是未来的包,缓存起来
+        g_ogg_out_of_order_count++;  // 增加错序计数器
+        printf("[LN_UDP] Dual stream: Received future packet sequence=%u (expected=%u), caching (out_of_order_count=%u)\n", 
+               sequence, g_ogg_expected_sequence, g_ogg_out_of_order_count);
+        
+        // 如果连续错序超过阈值,跳过期望的序列号(避免丢包时一直无法正常输出)
+        if (g_ogg_out_of_order_count > OGG_MAX_OUT_OF_ORDER_COUNT) {
+            uint32_t old_expected = g_ogg_expected_sequence;
+            printf("[LN_UDP] Dual stream: Out of order count exceeded %d, skipping sequence %u\n", 
+                   OGG_MAX_OUT_OF_ORDER_COUNT, g_ogg_expected_sequence);
+            
+            // 1. 先将期望序号往后加一(跳过丢失的包)
+            g_ogg_expected_sequence++;
+            g_ogg_out_of_order_count = 0;  // 重置计数器
+            
+            // 2. 处理缓存中的包(尝试解码并发送缓存中所有能处理的连续包)
+            ln_udp_dual_stream_flush_cache();
+            
+            // 3. 再尝试处理当前包
+            if (sequence == g_ogg_expected_sequence) {
+                // 当前包正好是期望的包,直接解码并发送
+                if (ln_udp_dual_stream_decode_and_send(sequence, data, data_size) == 0) {
+                    g_ogg_expected_sequence++;
+                    free((void *)data);
+                    // 继续刷新缓存中的后续包
+                    ln_udp_dual_stream_flush_cache();
+                    printf("[LN_UDP] Dual stream: Successfully decoded and sent skipped packet sequence=%u (old_expected=%u)\n", 
+                           sequence, old_expected);
+                    return 0;
+                } else {
+                    // 解码失败,缓存这个包
+                    ln_udp_ogg_cache_packet(sequence, data, data_size);
+                    free((void *)data);
+                    return -1;
+                }
+            } else if (sequence > g_ogg_expected_sequence) {
+                // 当前包仍然是未来的包,缓存起来
+                printf("[LN_UDP] Dual stream: Current packet sequence=%u still ahead of expected=%u after skip, caching\n", 
+                       sequence, g_ogg_expected_sequence);
+                ln_udp_ogg_cache_packet(sequence, data, data_size);
+                free((void *)data);
+                return 0;
+            } else {
+                // 当前包已经是过去的包(在刷新缓存时已处理),丢弃
+                printf("[LN_UDP] Dual stream: Current packet sequence=%u is now old (expected=%u), dropping\n", 
+                       sequence, g_ogg_expected_sequence);
+                free((void *)data);
+                return 0;
+            }
+        } else {
+            // 正常缓存未来包
+            ln_udp_ogg_cache_packet(sequence, data, data_size);
+            free((void *)data);
+            return 0;
+        }
+    } else {
+        // 是过去的包(重复或乱序),丢弃
+        printf("[LN_UDP] Dual stream: Received old/duplicate packet sequence=%u (expected=%u), dropping\n", 
+               sequence, g_ogg_expected_sequence);
+        free((void *)data);
+        return 0;
+    }
+}
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+/**
+ * @brief UDP接收线程
+ */
+static void ln_udp_recv_thread(void *arg)
+{
+    (void)arg;
+    uint8_t recv_buffer[UDP_RECV_BUFFER_SIZE];
+    struct sockaddr_in server_addr;
+    socklen_t addr_len = sizeof(server_addr);
+    
+    printf("[LN_UDP] Receive thread started\n");
+    
+    // 获取服务器地址信息
+    ln_mqtt_udp_info_t udp_info;
+    if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+        printf("[LN_UDP] UDP info not available in receive thread\n");
+        g_udp_thread_running = false;
+        return;
+    }
+    
+    // 设置服务器地址
+    memset(&server_addr, 0, sizeof(server_addr));
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = lwip_htons(udp_info.port);
+    server_addr.sin_addr.s_addr = inet_addr(udp_info.server);
+
+    
+    // printf("[LN_UDP] Ready to receive UDP packets from %s:%d\n", udp_info.server, udp_info.port);
+    
+    while (g_udp_thread_running && g_udp_socket >= 0) {
+        // 接收UDP数据(阻塞,超时1秒)
+        fd_set read_fds;
+        struct timeval timeout;
+        
+        FD_ZERO(&read_fds);
+        FD_SET(g_udp_socket, &read_fds);
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+        
+        int select_ret = lwip_select(g_udp_socket + 1, &read_fds, NULL, NULL, &timeout);
+        if (select_ret > 0 && FD_ISSET(g_udp_socket, &read_fds)) {
+            // 有数据可读
+            ssize_t recv_len = lwip_recvfrom(g_udp_socket, recv_buffer, sizeof(recv_buffer) - 1, 0,
+                                             (struct sockaddr *)&server_addr, &addr_len);
+            
+            if (recv_len > 0) {
+                printf("[LN_UDP] Received %d bytes\r\n", 
+                       (int)recv_len
+                    );
+                
+                // 处理接收到的数据(解包、解密)
+                ln_udp_process_received_data(recv_buffer, (uint16_t)recv_len);
+                
+            } else if (recv_len == 0) {
+                printf("[LN_UDP] Connection closed by peer\n");
+                break;
+            } else {
+                if (errno != EAGAIN && errno != EWOULDBLOCK) {
+                    printf("[LN_UDP] Recvfrom error: %s\n", strerror(errno));
+                }
+            }
+        } else if (select_ret < 0) {
+            if (errno != EINTR) {
+                printf("[LN_UDP] Select error: %s\n", strerror(errno));
+                break;
+            }
+        }
+        // select_ret == 0 表示超时,继续循环
+    }
+    
+    printf("[LN_UDP] Receive thread exited\n");
+    g_udp_thread_running = false;
+}
+
+/**
+ * @brief 创建UDP套接字
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_create_socket(void)
+{
+    // 获取UDP信息
+    ln_mqtt_udp_info_t udp_info;
+    if (ln_mqtt_api_get_udp_info(&udp_info) != 0) {
+        printf("[LN_UDP] UDP info not available, cannot create socket\n");
+        return -1;
+    }
+    
+    if (!udp_info.valid) {
+        printf("[LN_UDP] UDP info invalid, cannot create socket\n");
+        return -1;
+    }
+    
+    printf("[LN_UDP] Creating UDP socket for server: %s:%d\n", udp_info.server, udp_info.port);
+    
+    // 如果socket已存在,先关闭
+    if (g_udp_socket >= 0) {
+        printf("[LN_UDP] Closing existing UDP socket\n");
+        ln_udp_close_socket();
+    }
+    
+    // 创建UDP套接字
+    g_udp_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
+    if (g_udp_socket < 0) {
+        printf("[LN_UDP] Failed to create UDP socket: %s\n", strerror(errno));
+        return -1;
+    }
+    
+    // 设置socket选项(允许地址重用)
+    int opt = 1;
+    lwip_setsockopt(g_udp_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+    
+    // 设置为非阻塞模式(可选,用于select超时)
+    // int flags = lwip_fcntl(g_udp_socket, F_GETFL, 0);
+    // lwip_fcntl(g_udp_socket, F_SETFL, flags | O_NONBLOCK);
+    
+    printf("[LN_UDP] UDP socket created successfully, fd=%d\n", g_udp_socket);
+    
+    // 创建接收线程
+    if (!g_udp_thread_running) {
+        app_task_definition_ext_t recv_task = {
+            .attr = {
+                .name = "ln_udp_recv",
+                .stack_size = 0x8000,
+                .priority = osPriorityNormal
+            },
+            .func = ln_udp_recv_thread,
+            .task_handle = &g_udp_thread_handle,
+            .create_queue_handle = NULL,
+            .use_mem = USE_EXTEND_MEM,
+            .inst_args = NULL
+        };
+        
+        g_udp_thread_running = true;
+        errcode_t ret = uapi_create_osThread_custom_with_args(&recv_task);
+        if (ret != ERRCODE_SUCC) {
+            printf("[LN_UDP] ERROR: Failed to create receive thread: %d\n", ret);
+            g_udp_thread_running = false;
+            lwip_close(g_udp_socket);
+            g_udp_socket = -1;
+            return -1;
+        }
+        printf("[LN_UDP] Receive thread created successfully\n");
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 关闭UDP套接字
+ */
+void ln_udp_close_socket(void)
+{
+    // 完成并关闭 OGG 文件
+    if (g_ogg_initialized) {
+        ln_udp_ogg_complete_current_file();
+    }
+    
+    // 完成并关闭 Opus 调试文件
+#if ENABLE_OPUS_RAW_DEBUG
+    if (g_opus_debug_file != NULL) {
+        ln_udp_opus_debug_complete_current_file();
+    }
+#endif
+    
+    // 停止接收线程
+    if (g_udp_thread_running) {
+        printf("[LN_UDP] Stopping receive thread\n");
+        g_udp_thread_running = false;
+        
+        // 等待线程退出(最多等待2秒)
+        uint32_t timeout = osKernelGetTickCount() + osKernelGetTickFreq() * 2;
+        while (g_udp_thread_handle != 0 && osKernelGetTickCount() < timeout) {
+            osDelay(10);
+        }
+        
+        if (g_udp_thread_handle != 0) {
+            printf("[LN_UDP] WARNING: Receive thread did not exit in time\n");
+        }
+        
+        g_udp_thread_handle = 0;
+    }
+    
+    // 关闭套接字
+    if (g_udp_socket >= 0) {
+        printf("[LN_UDP] Closing UDP socket, fd=%d\n", g_udp_socket);
+        lwip_close(g_udp_socket);
+        g_udp_socket = -1;
+    }
+}
+
+/**
+ * @brief 获取UDP套接字文件描述符
+ * @return socket文件描述符,-1表示未创建
+ */
+int ln_udp_get_socket(void)
+{
+    return g_udp_socket;
+}
+
+/**
+ * @brief 检查UDP套接字是否已创建
+ * @return true 已创建,false 未创建
+ */
+bool ln_udp_is_socket_created(void)
+{
+    return (g_udp_socket >= 0);
+}
+
+// +------+-------+-------------+----------+------------+----------+-------------------+
+// | Type | Flags | Payload Len |   SSRC   | Timestamp  | Sequence | Encrypted Payload |
+// +------+-------+-------------+----------+------------+----------+-------------------+
+// |1 byte|1 byte |   2 bytes   | 4 bytes  |  4 bytes   | 4 bytes  |      N bytes      |
+// +------+-------+-------------+----------+------------+----------+-------------------+
+
+
+// import struct
+// from Crypto.Cipher import AES
+// from Crypto.Util import Counter
+
+// def encrypt_audio(key_hex: str, nonce_hex: str, timestamp: int, sequence: int, audio_data: bytes) -> bytes:
+//     """
+//     加密音频数据
+    
+//     Args:
+//         key_hex: 32字符十六进制密钥
+//         nonce_hex: 32字符十六进制nonce
+//         timestamp: 数据包时间戳
+//         sequence: 数据包序列号
+//         audio_data: 原始Opus音频数据
+    
+//     Returns:
+//         加密后的音频数据
+//     """
+//     key = bytes.fromhex(key_hex)
+//     nonce = bytes.fromhex(nonce_hex)
+    
+//     # 构建计数器初始值:结合timestamp和sequence
+//     counter_init = int.from_bytes(nonce[:12] + struct.pack('>I', sequence), 'big')
+//     ctr = Counter.new(128, initial_value=counter_init)
+    
+//     cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
+//     return cipher.encrypt(audio_data)
+
+// def decrypt_audio(key_hex: str, nonce_hex: str, timestamp: int, sequence: int, encrypted_data: bytes) -> bytes:
+//     """解密音频数据(与加密相同,CTR模式对称)"""
+//     return encrypt_audio(key_hex, nonce_hex, timestamp, sequence, encrypted_data)
+
+/**
+ * @brief 将十六进制字符串转换为字节数组
+ * @param hex_str 十六进制字符串(如 "01020304")
+ * @param output 输出的字节数组
+ * @param output_size 输出缓冲区大小
+ * @return 转换的字节数,-1表示失败
+ */
+static int hex_string_to_bytes(const char *hex_str, uint8_t *output, size_t output_size)
+{
+    if (!hex_str || !output) {
+        return -1;
+    }
+    
+    size_t hex_len = strlen(hex_str);
+    if (hex_len % 2 != 0 || hex_len / 2 > output_size) {
+        printf("[LN_UDP] Invalid hex string length: %zu\n", hex_len);
+        return -1;
+    }
+    
+    for (size_t i = 0; i < hex_len; i += 2) {
+        char hex_byte[3] = {hex_str[i], hex_str[i + 1], '\0'};
+        char *endptr;
+        unsigned long val = strtoul(hex_byte, &endptr, 16);
+        if (*endptr != '\0' || val > 255) {
+            printf("[LN_UDP] Invalid hex character at position %zu\n", i);
+            return -1;
+        }
+        output[i / 2] = (uint8_t)val;
+    }
+    
+    return (int)(hex_len / 2);
+}
+
+/**
+ * @brief 加密音频数据(AES-128-CTR模式)
+ * @param key_hex 32字符十六进制密钥
+ * @param base_nonce_hex 32字符十六进制基础nonce(从hello消息中获取的原始nonce)
+ * @param payload_len 负载长度(2字节,用于构造nonce)
+ * @param timestamp 时间戳(4字节,用于构造nonce)
+ * @param sequence 数据包序列号(4字节,用于构造nonce)
+ * @param audio_data 原始音频数据
+ * @param audio_len 音频数据长度
+ * @param encrypted_data 输出的加密数据缓冲区(由调用者分配,大小至少为audio_len)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_encrypt_audio(const char *key_hex, const char *base_nonce_hex, 
+                         uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+                         const uint8_t *audio_data, uint16_t audio_len, uint8_t *encrypted_data)
+{
+    if (!key_hex || !base_nonce_hex || !audio_data || !encrypted_data || audio_len == 0) {
+        printf("[LN_UDP] Invalid parameters for encryption\n");
+        return -1;
+    }
+    
+    // 转换密钥(32字符十六进制 = 16字节)
+    uint8_t key[16];
+    if (hex_string_to_bytes(key_hex, key, sizeof(key)) != 16) {
+        printf("[LN_UDP] Failed to convert key from hex\n");
+        return -1;
+    }
+    
+    // 转换基础nonce(32字符十六进制 = 16字节)
+    uint8_t base_nonce[16];
+    if (hex_string_to_bytes(base_nonce_hex, base_nonce, sizeof(base_nonce)) != 16) {
+        printf("[LN_UDP] Failed to convert base nonce from hex\n");
+        return -1;
+    }
+    
+    // 构造nonce:参考代码 std::string nonce(aes_nonce_);
+    // 然后修改特定位置:*(uint16_t*)&nonce[2] = htons(payload.size());
+    //                    *(uint32_t*)&nonce[8] = htonl(timestamp);
+    //                    *(uint32_t*)&nonce[12] = htonl(sequence);
+    uint8_t nonce_counter[16];
+    memcpy(nonce_counter, base_nonce, 16);  // 复制基础nonce
+    *(uint16_t*)&nonce_counter[2] = lwip_htons(payload_len);   // 位置2:payload长度(2字节)
+    *(uint32_t*)&nonce_counter[8] = lwip_htonl(timestamp);      // 位置8:时间戳(4字节)
+    *(uint32_t*)&nonce_counter[12] = lwip_htonl(sequence);     // 位置12:序列号(4字节)
+    
+    // 初始化AES上下文
+    mbedtls_aes_context aes_ctx;
+    mbedtls_aes_init(&aes_ctx);
+    
+    // 设置AES-128密钥(128位 = 16字节)
+    if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0) {
+        printf("[LN_UDP] Failed to set AES key\n");
+        mbedtls_aes_free(&aes_ctx);
+        return -1;
+    }
+    
+    // 使用AES-CTR模式加密(直接使用 mbedtls_aes_crypt_ctr)
+    size_t nc_off = 0;  // nonce counter offset(CTR模式内部使用)
+    uint8_t stream_block[16] = {0};  // stream block(CTR模式内部使用)
+
+    printf("nonce_counter: ");
+    for (int i = 0; i < 16; i++) {
+        printf("%02x ", nonce_counter[i]);
+    }
+    printf("\n");
+    
+    if (mbedtls_aes_crypt_ctr(&aes_ctx, audio_len, &nc_off, nonce_counter, stream_block,
+                               audio_data, encrypted_data) != 0) {
+        printf("[LN_UDP] Failed to encrypt audio data with AES-CTR\n");
+        mbedtls_aes_free(&aes_ctx);
+        return -1;
+    }
+    
+    mbedtls_aes_free(&aes_ctx);
+    
+    return 0;
+}
+
+/**
+ * @brief 解密音频数据(AES-128-CTR模式,与加密相同)
+ * @param key_hex 32字符十六进制密钥
+ * @param nonce_hex 32字符十六进制nonce
+ * @param sequence 数据包序列号
+ * @param encrypted_data 加密的音频数据
+ * @param encrypted_len 加密数据长度
+ * @param decrypted_data 输出的解密数据缓冲区(由调用者分配,大小至少为encrypted_len)
+ * @return 0 成功,-1 失败
+ */
+/**
+ * @brief 解密音频数据(AES-128-CTR模式,与加密相同)
+ * @param key_hex 32字符十六进制密钥
+ * @param base_nonce_hex 32字符十六进制基础nonce(从hello消息中获取的原始nonce)
+ * @param payload_len 负载长度(2字节,用于构造nonce)
+ * @param timestamp 时间戳(4字节,用于构造nonce)
+ * @param sequence 数据包序列号(4字节,用于构造nonce)
+ * @param encrypted_data 加密的音频数据
+ * @param encrypted_len 加密数据长度
+ * @param decrypted_data 输出的解密数据缓冲区(由调用者分配,大小至少为encrypted_len)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_decrypt_audio(const char *key_hex, const char *base_nonce_hex,
+                         uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+                         const uint8_t *encrypted_data, uint16_t encrypted_len, uint8_t *decrypted_data)
+{
+    // CTR模式是对称的,解密和加密使用相同的操作
+    return ln_udp_encrypt_audio(key_hex, base_nonce_hex, payload_len, timestamp, sequence,
+                                 encrypted_data, encrypted_len, decrypted_data);
+}
+
+/**
+ * @brief 完整的数据打包函数(加密+打包)
+ * @param audio_data 原始音频数据
+ * @param audio_len 音频数据长度
+ * @param buffer 输出缓冲区(由调用者分配,大小至少为 UDP_PACKET_HEADER_SIZE + audio_len)
+ * @param buffer_size 缓冲区大小
+ * @param out_len 输出的实际数据长度
+ * @return 0 成功,-1 失败
+ * @note 函数内部自动处理type、flags、ssrc、timestamp、sequence等字段
+ */
+int ln_udp_pack_audio_data(const uint8_t *audio_data, uint16_t audio_len,
+                           uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len)
+{
+    if (!audio_data || audio_len == 0 || !buffer || !out_len) {
+        printf("[LN_UDP] Invalid parameters for pack audio data\n");
+        return -1;
+    }
+    
+    // 计算所需缓冲区大小
+    uint16_t total_len = UDP_PACKET_HEADER_SIZE + audio_len;
+    if (buffer_size < total_len) {
+        printf("[LN_UDP] Buffer too small: need %d, have %d\n", total_len, buffer_size);
+        return -1;
+    }
+    
+    // 1. 获取UDP信息(用于加密)
+    ln_mqtt_udp_info_t udp_info;
+    if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+        printf("[LN_UDP] UDP info not available for encryption\n");
+        return -1;
+    }
+    // 01 00 00 00 1d 38 db 20 69 70 a0 da 00000000
+    // 2. 初始化SSRC(如果未初始化,从 nonce 字节数组的索引 4-8 提取,只取 4 个字节)
+    if (g_udp_ssrc == 0) {
+        // 先将 nonce_hex 转换为字节数组
+        uint8_t nonce_bytes[16];  // nonce 是 32 个十六进制字符 = 16 字节
+        if (hex_string_to_bytes(udp_info.nonce, nonce_bytes, sizeof(nonce_bytes)) == 16) {
+            // 从字节数组中取索引 4-7(4 个字节)作为 SSRC(大端序)
+            g_udp_ssrc = ((uint32_t)nonce_bytes[4] << 24) |
+                         ((uint32_t)nonce_bytes[5] << 16) |
+                         ((uint32_t)nonce_bytes[6] << 8) |
+                         ((uint32_t)nonce_bytes[7]);
+            printf("[LN_UDP] SSRC initialized from nonce bytes[4-7]: 0x%02X%02X%02X%02X -> 0x%08X\n",
+                   nonce_bytes[4], nonce_bytes[5], nonce_bytes[6], nonce_bytes[7], g_udp_ssrc);
+        } else {
+            printf("[LN_UDP] Failed to convert nonce to bytes, using default SSRC\n");
+            g_udp_ssrc = 0x12345678;
+        }
+    }
+    
+    // 3. 自动递增序列号
+    uint32_t sequence = g_udp_sequence++;
+    
+    // 4. 获取时间戳(使用系统时钟)
+    uint32_t timestamp = (uint32_t)osKernelGetTickCount();  // 使用系统tick作为时间戳
+    
+    // 5. 设置数据包类型和标志(使用默认值)
+    uint8_t type = 0x01;   // 默认类型
+    uint8_t flags = 0;  // 默认标志
+    
+    // 6. 加密音频数据(nonce在函数内部构造)
+    uint8_t *encrypted_payload = buffer + UDP_PACKET_HEADER_SIZE;
+    if (ln_udp_encrypt_audio(udp_info.key, udp_info.nonce, audio_len, timestamp, sequence,
+                             audio_data, audio_len, encrypted_payload) != 0) {
+        printf("[LN_UDP] Failed to encrypt audio data\n");
+        return -1;
+    }
+    
+    // 7. 打包数据包头部
+    uint8_t *ptr = buffer;
+    ptr[0] = type;
+    ptr[1] = flags;
+    *(uint16_t *)(ptr + 2) = lwip_htons(audio_len);  // payload_len(加密后的长度等于原始长度)
+    *(uint32_t *)(ptr + 4) = lwip_htonl(g_udp_ssrc);
+    *(uint32_t *)(ptr + 8) = lwip_htonl(timestamp);
+    *(uint32_t *)(ptr + 12) = lwip_htonl(sequence);
+    
+    // 加密的payload已经在步骤6中写入buffer + UDP_PACKET_HEADER_SIZE位置
+    
+    *out_len = total_len;
+
+    printf( "buffer: ");
+    for (int i = 0; i < 16; i++) {
+        printf("%02x ", buffer[i]);
+    }
+    printf("\n");
+    
+    printf("[LN_UDP] Audio data packed: type=%d, flags=%d, ssrc=0x%08X, timestamp=%u, sequence=%u, payload_len=%d, total_len=%d\n",
+           type, flags, g_udp_ssrc, timestamp, sequence, audio_len, total_len);
+    
+    return 0;
+}
+
+/**
+ * @brief 创建音频发送队列
+ */
+static void create_audio_send_queue(void)
+{
+    if (g_audio_send_queue != 0xFFFFFFFF) {
+        // 队列已创建
+        return;
+    }
+    
+    if (osal_msg_queue_create("ln_udp_audio_send_queue", AUDIO_SEND_QUEUE_SIZE, &g_audio_send_queue,
+                              0, sizeof(audio_send_msg_t)) != ERRCODE_SUCC) {
+        printf("[LN_UDP] Failed to create audio send queue\n");
+        g_audio_send_queue = 0xFFFFFFFF;
+    } else {
+        printf("[LN_UDP] Audio send queue created successfully\n");
+    }
+}
+
+/**
+ * @brief 音频数据发送线程
+ */
+static void ln_udp_audio_send_thread(void *arg)
+{
+    (void)arg;
+    audio_send_msg_t msg;
+    uint32_t msgsize = sizeof(audio_send_msg_t);
+    
+    printf("[LN_UDP] Audio send thread started\n");
+    
+    while (g_audio_send_thread_running) {
+        // 从队列读取音频数据(阻塞等待)
+        int32_t ret = osal_msg_queue_read_copy(g_audio_send_queue, (void *)&msg, &msgsize,
+                                               OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            printf("[LN_UDP] Failed to read from audio send queue: %d\n", ret);
+            continue;
+        }
+        
+        // 检查数据大小和数据指针
+        if (msg.size == 0 || msg.size > AUDIO_SEND_MAX_DATA_SIZE || msg.data == NULL) {
+            printf("[LN_UDP] Invalid audio data: size=%u, data=%p\n", msg.size, msg.data);
+            // 释放内存(如果存在)
+            if (msg.data != NULL) {
+                free(msg.data);
+            }
+            continue;
+        }
+        
+        // 确保 UDP socket 已创建
+        if (!ln_udp_is_socket_created()) {
+            printf("[LN_UDP] UDP socket not ready, drop audio frame\n");
+            free(msg.data);
+            continue;
+        }
+        
+        int sock = ln_udp_get_socket();
+        if (sock < 0) {
+            printf("[LN_UDP] UDP socket invalid, drop audio frame\n");
+            free(msg.data);
+            continue;
+        }
+        
+        // 打包(加密+UDP头)
+        uint8_t send_buf[UDP_PACKET_HEADER_SIZE + AUDIO_SEND_MAX_DATA_SIZE];
+        uint16_t out_len = 0;
+        if (ln_udp_pack_audio_data(msg.data, (uint16_t)msg.size, send_buf, 
+                                   (uint16_t)sizeof(send_buf), &out_len) != 0) {
+            printf("[LN_UDP] Failed to pack audio frame\n");
+            free(msg.data);
+            continue;
+        }
+        
+        // 获取UDP信息(用于发送)
+        ln_mqtt_udp_info_t udp_info;
+        if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+            printf("[LN_UDP] UDP info not available, drop audio frame\n");
+            free(msg.data);
+            continue;
+        }
+        
+        // 发送到服务器
+        struct sockaddr_in server_addr;
+        memset(&server_addr, 0, sizeof(server_addr));
+        server_addr.sin_family = AF_INET;
+        server_addr.sin_port = lwip_htons(udp_info.port);
+        server_addr.sin_addr.s_addr = inet_addr(udp_info.server);
+        
+        ssize_t sent = lwip_sendto(sock, send_buf, out_len, 0, 
+                                   (struct sockaddr *)&server_addr, sizeof(server_addr));
+        if (sent < 0) {
+            printf("[LN_UDP] UDP sendto failed: %s\n", strerror(errno));
+        }
+        
+        // 释放音频数据内存
+        free(msg.data);
+        msg.data = NULL;
+    }
+    
+    printf("[LN_UDP] Audio send thread exited\n");
+    g_audio_send_thread_running = false;
+}
+
+/**
+ * @brief 初始化音频发送队列和线程
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_init(void)
+{
+    // 创建消息队列
+    create_audio_send_queue();
+    if (g_audio_send_queue == 0xFFFFFFFF) {
+        printf("[LN_UDP] Failed to create audio send queue\n");
+        return -1;
+    }
+    
+    // 创建发送线程(如果尚未创建)
+    if (!g_audio_send_thread_running) {
+        app_task_definition_ext_t send_task = {
+            .attr = {
+                .name = "ln_udp_audio_send",
+                .stack_size = 0x2000,
+                .priority = osPriorityNormal
+            },
+            .func = ln_udp_audio_send_thread,
+            .task_handle = &g_audio_send_thread_handle,
+            .create_queue_handle = NULL,
+            .use_mem = USE_EXTEND_MEM,
+            .inst_args = NULL
+        };
+        
+        g_audio_send_thread_running = true;
+        errcode_t ret = uapi_create_osThread_custom_with_args(&send_task);
+        if (ret != ERRCODE_SUCC) {
+            printf("[LN_UDP] ERROR: Failed to create audio send thread: %d\n", ret);
+            g_audio_send_thread_running = false;
+            return -1;
+        }
+        printf("[LN_UDP] Audio send thread created successfully\n");
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 停止音频发送线程
+ */
+void ln_udp_audio_send_deinit(void)
+{
+    // 停止发送线程
+    if (g_audio_send_thread_running) {
+        printf("[LN_UDP] Stopping audio send thread\n");
+        g_audio_send_thread_running = false;
+        
+        // 发送一个空消息唤醒线程(如果队列为空)
+        // 注意:data 为 NULL,size 为 0,线程会检查并释放
+        audio_send_msg_t wake_msg = {0};
+        wake_msg.data = NULL;
+        wake_msg.size = 0;
+        osal_msg_queue_write_copy(g_audio_send_queue, (void *)&wake_msg, sizeof(audio_send_msg_t), 0);
+        
+        // 等待线程退出(最多等待2秒)
+        uint32_t timeout = osKernelGetTickCount() + osKernelGetTickFreq() * 2;
+        while (g_audio_send_thread_handle != 0 && osKernelGetTickCount() < timeout) {
+            osDelay(10);
+        }
+        
+        if (g_audio_send_thread_handle != 0) {
+            printf("[LN_UDP] WARNING: Audio send thread did not exit in time\n");
+        }
+        
+        g_audio_send_thread_handle = 0;
+    }
+    
+    // 清空队列中剩余的消息(释放内存)
+    if (g_audio_send_queue != 0xFFFFFFFF) {
+        audio_send_msg_t msg;
+        uint32_t msgsize = sizeof(audio_send_msg_t);
+        while (osal_msg_queue_read_copy(g_audio_send_queue, (void *)&msg, &msgsize, 0) == OSAL_SUCCESS) {
+            if (msg.data != NULL) {
+                free(msg.data);
+            }
+            msgsize = sizeof(audio_send_msg_t);
+        }
+    }
+    
+    // 删除消息队列
+    if (g_audio_send_queue != 0xFFFFFFFF) {
+        osal_msg_queue_delete(g_audio_send_queue);
+        g_audio_send_queue = 0xFFFFFFFF;
+        printf("[LN_UDP] Audio send queue deleted\n");
+    }
+}
+
+/**
+ * @brief 将音频数据放入发送队列(供录音回调函数调用)
+ * @param data 音频数据指针
+ * @param size 音频数据大小
+ * @return 0 成功,-1 失败
+ * @note 函数内部会动态分配内存并复制数据,发送线程负责释放内存
+ */
+int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size)
+{
+    if (!data || size == 0 || size > AUDIO_SEND_MAX_DATA_SIZE) {
+        printf("[LN_UDP] Invalid parameters for audio send enqueue\n");
+        return -1;
+    }
+    
+    if (g_audio_send_queue == 0xFFFFFFFF) {
+        printf("[LN_UDP] Audio send queue not initialized\n");
+        return -1;
+    }
+    
+    // 动态分配内存并复制数据
+    uint8_t *data_copy = (uint8_t *)malloc(size);
+    if (data_copy == NULL) {
+        printf("[LN_UDP] Failed to allocate memory for audio data\n");
+        return -1;
+    }
+    memcpy(data_copy, data, size);
+    
+    // 构造消息
+    audio_send_msg_t msg;
+    msg.data = data_copy;
+    msg.size = size;
+    
+    // 写入队列(非阻塞,如果队列满则丢弃并释放内存)
+    int32_t ret = osal_msg_queue_write_copy(g_audio_send_queue, (void *)&msg, sizeof(audio_send_msg_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        printf("[LN_UDP] Failed to enqueue audio data: %d (queue may be full)\n", ret);
+        free(data_copy);  // 队列满时释放内存
+        return -1;
+    }
+    
+    return 0;
+}
\ No newline at end of file
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.c b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.c
new file mode 100644 (file)
index 0000000..6638bd5
--- /dev/null
@@ -0,0 +1,921 @@
+#include "ln_api.h"
+#include "ln_mqtt_api.h"
+#include "uapi_Mqtt_api.h"
+#include "lwip/apps/mqtt.h"
+#include "lwip/err.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "wearable_log.h"
+#include "custom_utils.h"
+#include "ai_media.h"
+#include "audio_base_type.h"
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+#include "lwip/netdb.h"
+
+#define LN_MQTT_SEND_TOPIC "device-server-enhanced"
+
+/* MQTT API 全局状态 */
+static bool g_ln_mqtt_service_started = false;
+
+/* UDP信息全局变量 */
+static ln_mqtt_udp_info_t g_udp_info = {0};
+
+/* hello 消息中的 session_id(用于后续 listen 控制消息) */
+static char g_ln_mqtt_session_id[64] = {0};
+static bool g_ln_mqtt_session_id_valid = false;
+
+/* 音频初始化状态标志位 */
+static volatile bool g_mqtt_audio_initialized = false;
+
+int ln_mqtt_api_send_hello(void);
+
+// --- MQTT 录音(来自 ai_media_service_mqtt.cpp,无对应头文件时在此声明) ---
+typedef void (*MqttRecordDataCallback)(const uint8_t* data, uint32_t size, void* userData);
+typedef struct {
+    int32_t audioFormat;
+    uint32_t channelCount;
+    uint32_t sampleRate;
+} MqttRecordAudioParams;
+extern int32_t MQTT_StartRecord(MqttRecordDataCallback dataCallback, void* userData,
+                                const MqttRecordAudioParams* audioParams);
+extern int32_t MQTT_StopRecord(void);
+
+// --- LN UDP(定义在 ln_UPD.c)---
+extern int ln_udp_create_socket(void);
+extern bool ln_udp_is_socket_created(void);
+extern int ln_udp_get_socket(void);
+extern int ln_udp_pack_audio_data(const uint8_t *audio_data, uint16_t audio_len,
+                                  uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len);
+extern int ln_udp_audio_send_init(void);
+extern void ln_udp_audio_send_deinit(void);
+extern int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size);
+
+#define LN_UDP_PACKET_HEADER_SIZE 16
+#define LN_MQTT_RECORD_MAX_FRAME   0x800
+#define LN_MQTT_RECORD_BATCH_SIZE  5  // 每5包数据合并后入队
+
+/* 双流接口开关:定义 USE_DUAL_STREAM_INTERFACE 则使用 old_Start_AIVoice 双流接口,否则使用 MQTT_StartRecord */
+/* 可在 CMakeLists.txt 或编译选项中定义,例如:-DUSE_DUAL_STREAM_INTERFACE=1 */
+
+
+/* 音频数据缓存结构体(用于批量入队) */
+typedef struct {
+    uint8_t *buffer;         // 缓存缓冲区指针(动态分配)
+    uint32_t buffer_size;    // 缓冲区大小
+    uint32_t current_size;   // 当前缓存的数据大小
+    uint32_t packet_count;   // 当前累积的包数
+} ln_mqtt_record_cache_t;
+
+/* 全局缓存变量 */
+static ln_mqtt_record_cache_t g_record_cache = {0};
+
+#if USE_DUAL_STREAM_INTERFACE
+/* 录音上传状态标志位(用于控制是否处理并上传音频数据) */
+static volatile bool g_recording_upload_started = false;
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+static void ln_mqtt_record_data_cb(const uint8_t* data, uint32_t size, void* userData)
+{
+    (void)userData;
+    if (!data || size == 0) {
+        return;
+    }
+    if (size > LN_MQTT_RECORD_MAX_FRAME) {
+        printf("[LN_MQTT_API] Record frame too large: %u\n", (unsigned)size);
+        return;
+    }
+
+#if USE_DUAL_STREAM_INTERFACE
+    // 如果录音上传未开始,只缓存数据,不处理上传
+    if (!g_recording_upload_started) {
+        // 可以在这里缓存数据,等待开始标志位设置后再处理
+        // 目前先直接返回,不处理数据
+        return;
+    }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+    printf("ln_mqtt_record_data_cb size %d\r\n",size);
+
+    // 如果缓冲区未分配,先分配
+    if (g_record_cache.buffer == NULL) {
+        uint32_t initial_size = LN_MQTT_RECORD_MAX_FRAME * LN_MQTT_RECORD_BATCH_SIZE;
+        g_record_cache.buffer = (uint8_t *)malloc(initial_size);
+        if (g_record_cache.buffer == NULL) {
+            printf("[LN_MQTT_API] Failed to allocate cache buffer, drop frame\n");
+            return;
+        }
+        g_record_cache.buffer_size = initial_size;
+        g_record_cache.current_size = 0;
+        g_record_cache.packet_count = 0;
+        printf("[LN_MQTT_API] Cache buffer allocated: %u bytes\n", initial_size);
+    }
+
+    // 检查缓存是否足够大,如果不够则扩容
+    if (g_record_cache.current_size + size > g_record_cache.buffer_size) {
+        printf("[LN_MQTT_API] Cache overflow, force flush: current=%u, new=%u, max=%u\n",
+               g_record_cache.current_size, size, g_record_cache.buffer_size);
+        // 如果缓存已满,强制刷新当前缓存
+        if (g_record_cache.current_size > 0) {
+            if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+                printf("[LN_MQTT_API] Failed to enqueue cached audio data\n");
+            }
+            g_record_cache.current_size = 0;
+            g_record_cache.packet_count = 0;
+        }
+    }
+
+    // 将数据添加到缓存
+    memcpy(g_record_cache.buffer + g_record_cache.current_size, data, size);
+    g_record_cache.current_size += size;
+    g_record_cache.packet_count++;
+
+    // 如果累积到5包,将缓存数据入队
+    if (g_record_cache.packet_count >= LN_MQTT_RECORD_BATCH_SIZE) {
+        if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+            printf("[LN_MQTT_API] Failed to enqueue batched audio data, drop frame\n");
+        } else {
+            printf("[LN_MQTT_API] Enqueued %u packets, total size: %u bytes\n",
+                   g_record_cache.packet_count, g_record_cache.current_size);
+        }
+        // 清空缓存
+        g_record_cache.current_size = 0;
+        g_record_cache.packet_count = 0;
+    }
+
+    msleep(10);
+}
+
+/**
+ * @brief 解析hello类型消息并保存UDP信息
+ * @param data JSON数据(完整数据,以null结尾)
+ * @return 0 成功,-1 失败
+ */
+static int ln_mqtt_handle_hello_message(const char *data);
+
+/**
+ * @brief 统一的消息解析函数,根据type字段分发到不同的处理函数
+ * @param data 原始数据
+ * @param len 数据长度
+ * @return 0 成功处理,-1 失败或未处理
+ */
+static int ln_mqtt_parse_message_by_type(const uint8_t *data, uint16_t len)
+{
+    if (!data || len == 0) {
+        return -1;
+    }
+    
+    // 确保字符串以null结尾
+    char *json_str = (char *)malloc(len + 1);
+    if (!json_str) {
+        printf("[LN_MQTT_API] Failed to allocate memory for JSON string\n");
+        return -1;
+    }
+    memcpy(json_str, data, len);
+    json_str[len] = '\0';
+    
+    // 解析JSON
+    cJSON *root = cJSON_Parse(json_str);
+    if (!root) {
+        const char *error_ptr = cJSON_GetErrorPtr();
+        if (error_ptr != NULL) {
+            printf("[LN_MQTT_API] JSON parse error: %s\n", error_ptr);
+        }
+        free(json_str);
+        return -1;
+    }
+    
+    // 获取type字段
+    cJSON *type_item = cJSON_GetObjectItemCaseSensitive(root, "type");
+    if (!cJSON_IsString(type_item)) {
+        printf("[LN_MQTT_API] No 'type' field or invalid type field in message\n");
+        cJSON_Delete(root);
+        free(json_str);
+        return -1;
+    }
+    
+    const char *type_value = type_item->valuestring;
+    printf("[LN_MQTT_API] Message type detected: %s\n", type_value);
+
+    printf("[LN_MQTT_API] Message: %s\n", json_str);
+    
+    // 根据type值调用相应的处理函数
+    int ret = -1;
+    if (strcmp(type_value, "hello") == 0) {
+        ret = ln_mqtt_handle_hello_message(json_str);
+        if(ret==0)
+        {
+            extern int ln_udp_create_socket(void);
+            ln_udp_create_socket();
+        }
+    } else {
+        printf("[LN_MQTT_API] Unknown message type: %s, skipping\n", type_value);
+    }
+    
+    cJSON_Delete(root);
+    free(json_str);
+    return ret;
+}
+
+
+
+// {
+//     "type": "hello",
+//     "version": 3,
+//     "session_id": "3326285112",
+//     "transport": "udp",
+//     "features": {
+//       "voice": true,
+//       "tts": true,
+//       "asr": true,
+//       "mcp": true
+//     },
+//     "udp": {
+//       "server": "192.168.2.200",
+//       "port": 50000,
+//       "encryption": "aes-128-ctr",
+//       "key": "90470f78e3edffc2bf5130d8d73b5d80",
+//       "nonce": "01000000a8bdec683dbe440fa41ec435"
+//     },
+//     "audio_params": {
+//       "format": "opus",
+//       "sample_rate": 16000,
+//       "channels": 1,
+//       "frame_duration": 60
+//     }
+//   }
+/**
+ * @brief 解析hello类型消息并保存UDP信息
+ * @param data JSON数据(完整数据,以null结尾)
+ * @return 0 成功,-1 失败
+ */
+static int ln_mqtt_handle_hello_message(const char *data)
+{
+    if (!data) {
+        printf("[LN_MQTT_API] Invalid data for parsing hello message\n");
+        return -1;
+    }
+    
+    // 解析JSON
+    cJSON *root = cJSON_Parse(data);
+    if (!root) {
+        const char *error_ptr = cJSON_GetErrorPtr();
+        if (error_ptr != NULL) {
+            printf("[LN_MQTT_API] JSON parse error: %s\n", error_ptr);
+        }
+        return -1;
+    }
+    
+    printf("[LN_MQTT_API] Parsing hello message...\n");
+
+    // 提取并保存 session_id(供后续 listen 消息使用)
+    cJSON *session_id_item = cJSON_GetObjectItemCaseSensitive(root, "session_id");
+    if (cJSON_IsString(session_id_item) && session_id_item->valuestring && session_id_item->valuestring[0] != '\0') {
+        strncpy(g_ln_mqtt_session_id, session_id_item->valuestring, sizeof(g_ln_mqtt_session_id) - 1);
+        g_ln_mqtt_session_id[sizeof(g_ln_mqtt_session_id) - 1] = '\0';
+        g_ln_mqtt_session_id_valid = true;
+        printf("[LN_MQTT_API] session_id saved: %s\n", g_ln_mqtt_session_id);
+    } else {
+        // 不直接失败:UDP 信息可能仍然有效
+        g_ln_mqtt_session_id[0] = '\0';
+        g_ln_mqtt_session_id_valid = false;
+        printf("[LN_MQTT_API] WARNING: session_id missing or invalid in hello message\n");
+    }
+    
+    // 解析UDP信息
+    cJSON *udp_item = cJSON_GetObjectItemCaseSensitive(root, "udp");
+    if (udp_item && cJSON_IsObject(udp_item)) {
+        // 清空之前的UDP信息
+        memset(&g_udp_info, 0, sizeof(g_udp_info));
+        
+        // 解析server
+        cJSON *server_item = cJSON_GetObjectItemCaseSensitive(udp_item, "server");
+        if (cJSON_IsString(server_item)) {
+            strncpy(g_udp_info.server, server_item->valuestring, sizeof(g_udp_info.server) - 1);
+            g_udp_info.server[sizeof(g_udp_info.server) - 1] = '\0';
+            printf("[LN_MQTT_API] UDP server: %s\n", g_udp_info.server);
+        }
+        
+        // 解析port
+        cJSON *port_item = cJSON_GetObjectItemCaseSensitive(udp_item, "port");
+        if (cJSON_IsNumber(port_item)) {
+            g_udp_info.port = (uint16_t)port_item->valueint;
+            printf("[LN_MQTT_API] UDP port: %d\n", g_udp_info.port);
+        }
+        
+        // 解析encryption
+        cJSON *encryption_item = cJSON_GetObjectItemCaseSensitive(udp_item, "encryption");
+        if (cJSON_IsString(encryption_item)) {
+            strncpy(g_udp_info.encryption, encryption_item->valuestring, sizeof(g_udp_info.encryption) - 1);
+            g_udp_info.encryption[sizeof(g_udp_info.encryption) - 1] = '\0';
+            printf("[LN_MQTT_API] UDP encryption: %s\n", g_udp_info.encryption);
+        }
+        
+        // 解析key
+        cJSON *key_item = cJSON_GetObjectItemCaseSensitive(udp_item, "key");
+        if (cJSON_IsString(key_item)) {
+            strncpy(g_udp_info.key, key_item->valuestring, sizeof(g_udp_info.key) - 1);
+            g_udp_info.key[sizeof(g_udp_info.key) - 1] = '\0';
+            printf("[LN_MQTT_API] UDP key: %s\n", g_udp_info.key);
+        }
+        
+        // 解析nonce
+        cJSON *nonce_item = cJSON_GetObjectItemCaseSensitive(udp_item, "nonce");
+        if (cJSON_IsString(nonce_item)) {
+            strncpy(g_udp_info.nonce, nonce_item->valuestring, sizeof(g_udp_info.nonce) - 1);
+            g_udp_info.nonce[sizeof(g_udp_info.nonce) - 1] = '\0';
+            printf("[LN_MQTT_API] UDP nonce: %s\n", g_udp_info.nonce);
+        }
+        
+        // 标记信息有效
+        if (g_udp_info.server[0] != '\0' && g_udp_info.port > 0) {
+            g_udp_info.valid = true;
+            printf("[LN_MQTT_API] UDP info saved successfully\n");
+        } else {
+            printf("[LN_MQTT_API] WARNING: UDP info incomplete (server or port missing)\n");
+        }
+    } else {
+        printf("[LN_MQTT_API] No UDP information in hello message\n");
+    }
+    
+    cJSON_Delete(root);
+    return 0;
+}
+
+/**
+ * @brief 自动订阅 devices/p2p/{clientId} 主题
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_auto_subscribe_p2p(void)
+{
+    char client_id[256] = {0};
+    if (uapi_mqtt_get_client_id(client_id, sizeof(client_id)) != 0) {
+        printf("[LN_MQTT_API] Warning: client_id not available for auto-subscribe\n");
+        return -1;
+    }
+    
+    char p2p_topic[256] = {0};
+    int ret = snprintf(p2p_topic, sizeof(p2p_topic), "devices/p2p/%s", client_id);
+    if (ret <= 0 || ret >= (int)sizeof(p2p_topic)) {
+        printf("[LN_MQTT_API] Failed to construct p2p topic (buffer too small)\n");
+        return -1;
+    }
+    
+    printf("[LN_MQTT_API] Auto-subscribing to topic: %s\n", p2p_topic);
+    
+    int subscribe_ret = uapi_mqtt_subscribe(p2p_topic, 1);
+    if (subscribe_ret == 0) {
+        printf("[LN_MQTT_API] Auto-subscribe request sent successfully\n");
+        return 0;
+    } else {
+        printf("[LN_MQTT_API] Auto-subscribe request failed: %d\n", subscribe_ret);
+        return -1;
+    }
+}
+
+/**
+ * @brief MQTT连接状态回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_connect_cb(void *arg, int status)
+{
+    (void)arg;
+    
+    printf("[LN_MQTT_API] Connection status changed: %d\n", status);
+    
+    // 连接成功时(status == 0 对应 MQTT_CONNECT_ACCEPTED),自动订阅和发送通知
+    if (status == 0) {
+        // 自动订阅 devices/p2p/{clientId} 主题
+        ln_mqtt_api_auto_subscribe_p2p();
+        
+        // 发送连接通知消息
+      
+    }
+    else
+    {
+        extern void ln_udp_close_socket(void);
+        ln_udp_close_socket();
+    }
+}
+
+/**
+ * @brief MQTT消息接收回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+    (void)arg;
+    
+    printf("[LN_MQTT_API] Message received - Topic: %s, Length: %d\n", topic ? topic : "NULL", len);
+    
+    // 统一解析消息,根据type字段分发处理
+    if (data && len > 0) {
+        ln_mqtt_parse_message_by_type(data, len);
+    }
+}
+
+/**
+ * @brief MQTT订阅结果回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_subscribe_cb(void *arg, const char *topic, uint8_t qos, int result)
+{
+    (void)arg;
+    
+    if (result == 0) {
+        printf("[LN_MQTT_API] Subscribe successful - Topic: %s, QoS: %d\n", topic ? topic : "NULL", qos);
+
+        // ln_mqtt_api_send_connection_notification();
+
+        ln_mqtt_api_send_hello();
+
+    } else {
+        printf("[LN_MQTT_API] Subscribe failed - Topic: %s, QoS: %d, Result: %d\n", topic ? topic : "NULL", qos, result);
+    }
+}
+
+/**
+ * @brief 启动MQTT服务(启动线程、自动连接等)
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_start_service(void)
+{
+    if (g_ln_mqtt_service_started) {
+        WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Service already started");
+        return 0;
+    }
+    
+    printf("[LN_MQTT_API] Starting MQTT service\n");
+    
+    // 构建回调函数结构体,使用内部回调
+    mqtt_call_backs_t callbacks = {0};
+    callbacks.connect_callback = ln_mqtt_internal_connect_cb;
+    callbacks.message_callback = ln_mqtt_internal_message_cb;
+    callbacks.subscribe_callback = ln_mqtt_internal_subscribe_cb;
+    callbacks.user_arg = NULL;
+    callbacks.main_thread_interval_ms = 1000;  // 默认1000ms
+    
+    // 启动MQTT主线程(会自动初始化、连接和管理消息队列)
+    int ret = uapi_mqtt_main_start(&callbacks);
+    if (ret != 0) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Failed to start MQTT service");
+        return -1;
+    }
+    
+    // 初始化音频发送队列和线程
+    if (ln_udp_audio_send_init() != 0) {
+        printf("[LN_MQTT_API] WARNING: Failed to init audio send queue/thread\n");
+        // 不影响服务启动,继续执行
+    }
+    
+#if USE_DUAL_STREAM_INTERFACE
+    // 使用 old_Start_AIVoice 接口时,在服务初始化时就启动音频
+    printf("[LN_MQTT_API] Initializing audio with old_Start_AIVoice dual stream interface\n");
+    
+    // 检查 AI 语音服务是否已经在运行(如果已运行则先停止)
+    if (AI_IsVoiceServiceRunning()) {
+        printf("[LN_MQTT_API] AI voice service already running, stopping it first\n");
+        StopAIVoice();
+    }
+    
+    // 设置第二个上行流参数:SBC 格式,16kHz,单声道
+    AIVoiceAudioParams secondStreamParams = {
+        .audioFormat = SBC,        // SBC 格式(对应 AudioCodecFormat)
+        .channelCount = 1,         // 单声道
+        .sampleRate = 16000        // 16kHz 采样率
+    };
+    
+    // 输入流参数(主输入流)
+    AIVoiceAudioParams inputParams = {
+        .audioFormat = SBC,
+        .channelCount = 1,
+        .sampleRate = 16000
+    };
+
+
+    
+    // 输出流参数(设置为NULL,因为我们只关心录音输入)
+    AIVoiceAudioParams outputParams = {
+        .audioFormat = PCM,
+        .channelCount = 1,
+        .sampleRate = 16000
+    };
+    
+    // 使用 old_Start_AIVoice 启动,传入第二个上行流参数启用双流
+    int32_t start_ret = old_Start_AIVoice(
+        (AIVoiceDataCallback)ln_mqtt_record_data_cb,  // 数据回调函数(类型转换)
+        NULL,                                          // 用户数据
+        &inputParams,                                  // 输入流参数(主输入流)
+        &outputParams,                                  // 输出流参数(NULL使用默认)
+        NULL,                          // 第二个上行流参数(启用双流)
+        false                                          // 不使用OGG封装
+    );
+    
+    if (start_ret != 0) {
+        printf("[LN_MQTT_API] WARNING: old_Start_AIVoice failed during service init: %d\n", (int)start_ret);
+        // 不影响服务启动,继续执行
+    } else {
+        printf("[LN_MQTT_API] old_Start_AIVoice initialized successfully (SBC, 16kHz, mono)\n");
+    }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+    
+    g_ln_mqtt_service_started = true;
+    printf("[LN_MQTT_API] MQTT service started successfully\n");
+    
+    return 0;
+}
+
+/**
+ * @brief 停止MQTT服务(停止线程、断开连接、清理资源等)
+ */
+void ln_mqtt_api_stop_service(void)
+{
+    if (!g_ln_mqtt_service_started) {
+        return;
+    }
+    
+    printf("[LN_MQTT_API] Stopping MQTT service\n");
+    
+    // 停止音频发送线程
+    ln_udp_audio_send_deinit();
+    
+    // 释放缓存缓冲区(如果存在)
+    if (g_record_cache.buffer != NULL) {
+        // 如果有剩余数据,先刷新
+        if (g_record_cache.current_size > 0) {
+            printf("[LN_MQTT_API] Flushing remaining cached audio data before service stop\n");
+            if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+                printf("[LN_MQTT_API] Failed to enqueue remaining cached audio data\n");
+            }
+        }
+        free(g_record_cache.buffer);
+        g_record_cache.buffer = NULL;
+        g_record_cache.buffer_size = 0;
+        g_record_cache.current_size = 0;
+        g_record_cache.packet_count = 0;
+        printf("[LN_MQTT_API] Cache buffer freed\n");
+    }
+    
+#if USE_DUAL_STREAM_INTERFACE
+    // 清理双流接口资源
+    // 清除录音上传标志位
+    g_recording_upload_started = false;
+    // 停止 AI 语音服务(在服务初始化时已启动)
+    if (AI_IsVoiceServiceRunning()) {
+        (void)StopAIVoice();
+        printf("[LN_MQTT_API] AI voice service stopped\n");
+    }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+    
+    // 停止MQTT主线程(会自动断开连接和清理资源)
+    uapi_mqtt_main_stop();
+    
+    g_ln_mqtt_service_started = false;
+    
+    printf("[LN_MQTT_API] MQTT service stopped\n");
+}
+
+
+/**
+ * @brief 断开MQTT连接
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_disconnect(void)
+{
+    if (g_ln_mqtt_service_started) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Service is running, use ln_mqtt_api_stop_service instead");
+        return -1;
+    }
+    
+    printf("[LN_MQTT_API] Disconnecting MQTT\n");
+    
+    int ret = uapi_mqtt_disconnect();
+    if (ret != 0) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Failed to disconnect MQTT");
+        return -1;
+    }
+    
+    return 0;
+}
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool ln_mqtt_api_is_connected(void)
+{
+    if (g_ln_mqtt_service_started) {
+        // 服务模式下,通过状态查询
+        int state = uapi_mqtt_main_get_state();
+        return (state == 2);  // 2 = MQTT_STATE_CONNECTED
+    }
+    
+    return uapi_mqtt_is_connected();
+}
+
+/**
+ * @brief 发送MQTT连接通知消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_connection_notification(void)
+{
+    if (!uapi_mqtt_is_connected()) {
+        printf("[LN_MQTT_API] Client not connected, cannot send connection notification\n");
+        return -1;
+    }
+    
+    char client_id[256] = {0};
+    if (uapi_mqtt_get_client_id(client_id, sizeof(client_id)) != 0) {
+        printf("[LN_MQTT_API] client_id not available, cannot send connection notification\n");
+        return -1;
+    }
+    
+    // 构建JSON数据
+    cJSON *root = cJSON_CreateObject();
+    if (!root) {
+        printf("[LN_MQTT_API] Failed to create JSON object\n");
+        return -1;
+    }
+    
+    cJSON_AddStringToObject(root, "clientId", client_id);
+    
+    cJSON *data = cJSON_CreateObject();
+    if (!data) {
+        printf("[LN_MQTT_API] Failed to create data object\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    cJSON_AddStringToObject(data, "type", "connected");
+    cJSON_AddItemToObject(root, "data", data);
+    
+    char *json_str = cJSON_Print(root);
+    if (!json_str) {
+        printf("[LN_MQTT_API] Failed to create JSON string\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    // 确定发布主题
+    char publish_topic[128] = {0};
+    const char *use_topic = NULL;
+    if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+        use_topic = publish_topic;
+    } else {
+        use_topic = LN_MQTT_SEND_TOPIC;  // 使用默认主题
+    }
+    
+    printf("[LN_MQTT_API] Publishing connection notification to topic: %s\n", use_topic);
+    printf("[LN_MQTT_API] Message: %s\n", json_str);
+    
+    uint16_t msg_len = (uint16_t)strlen(json_str);
+    int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+    
+    cJSON_free(json_str);
+    cJSON_Delete(root);
+    
+    if (ret == 0) {
+        printf("[LN_MQTT_API] Connection notification queued for sending successfully\n");
+        return 0;
+    } else {
+        printf("[LN_MQTT_API] Failed to queue connection notification: %d\n", ret);
+        return -1;
+    }
+}
+
+/**
+ * @brief 发送MQTT hello消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_hello(void)
+{
+    if (!uapi_mqtt_is_connected()) {
+        printf("[LN_MQTT_API] Client not connected, cannot send hello message\n");
+        return -1;
+    }
+    
+    // 构建JSON数据
+    cJSON *root = cJSON_CreateObject();
+    if (!root) {
+        printf("[LN_MQTT_API] Failed to create JSON object\n");
+        return -1;
+    }
+    
+    cJSON_AddStringToObject(root, "type", "hello");
+    cJSON_AddNumberToObject(root, "version", 3);
+    cJSON_AddStringToObject(root, "transport", "udp");
+    
+    // 添加 features 对象
+    cJSON *features = cJSON_CreateObject();
+    if (!features) {
+        printf("[LN_MQTT_API] Failed to create features object\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    cJSON_AddTrueToObject(features, "mcp");
+    cJSON_AddTrueToObject(features, "voice");
+    cJSON_AddItemToObject(root, "features", features);
+    
+    // 添加 audio_params 对象
+    cJSON *audio_params = cJSON_CreateObject();
+    if (!audio_params) {
+        printf("[LN_MQTT_API] Failed to create audio_params object\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    cJSON_AddStringToObject(audio_params, "format", "sbc");
+    cJSON_AddNumberToObject(audio_params, "sample_rate", 16000);
+    cJSON_AddNumberToObject(audio_params, "channels", 1);
+    cJSON_AddNumberToObject(audio_params, "frame_duration", 60);
+    cJSON_AddItemToObject(root, "audio_params", audio_params);
+    
+    char *json_str = cJSON_Print(root);
+    if (!json_str) {
+        printf("[LN_MQTT_API] Failed to create JSON string\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+    
+    // 确定发布主题
+    char publish_topic[128] = {0};
+    const char *use_topic = NULL;
+    if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+        use_topic = publish_topic;
+    } else {
+        use_topic = LN_MQTT_SEND_TOPIC;  // 使用默认主题
+    }
+    
+    printf("[LN_MQTT_API] Publishing hello message to topic: %s\n", use_topic);
+    printf("[LN_MQTT_API] Message: %s\n", json_str);
+    
+    uint16_t msg_len = (uint16_t)strlen(json_str);
+    int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+    
+    cJSON_free(json_str);
+    cJSON_Delete(root);
+    
+    if (ret == 0) {
+        printf("[LN_MQTT_API] Hello message queued for sending successfully\n");
+        return 0;
+    } else {
+        printf("[LN_MQTT_API] Failed to queue hello message: %d\n", ret);
+        return -1;
+    }
+}
+
+/**
+ * @brief 发送 listen 控制消息
+ * payload 示例:
+ * {
+ *   "session_id": "3326285112",
+ *   "type": "listen",
+ *   "state": "start|stop",
+ *   "mode": "auto"
+ * }
+ */
+int ln_mqtt_api_send_listen_state(bool start)
+{
+    if (!uapi_mqtt_is_connected()) {
+        printf("[LN_MQTT_API] Client not connected, cannot send listen message\n");
+        return -1;
+    }
+    if (!g_ln_mqtt_session_id_valid || g_ln_mqtt_session_id[0] == '\0') {
+        printf("[LN_MQTT_API] session_id not ready (missing hello?), cannot send listen message\n");
+        return -1;
+    }
+
+    // 构建JSON数据
+    cJSON *root = cJSON_CreateObject();
+    if (!root) {
+        printf("[LN_MQTT_API] Failed to create JSON object\n");
+        return -1;
+    }
+
+    cJSON_AddStringToObject(root, "session_id", g_ln_mqtt_session_id);
+    cJSON_AddStringToObject(root, "type", "listen");
+    cJSON_AddStringToObject(root, "state", start ? "start" : "stop");
+    cJSON_AddStringToObject(root, "mode", "auto");
+
+    char *json_str = cJSON_Print(root);
+    if (!json_str) {
+        printf("[LN_MQTT_API] Failed to create JSON string\n");
+        cJSON_Delete(root);
+        return -1;
+    }
+
+    // 确定发布主题
+    char publish_topic[128] = {0};
+    const char *use_topic = NULL;
+    if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+        use_topic = publish_topic;
+    } else {
+        use_topic = LN_MQTT_SEND_TOPIC;  // 使用默认主题
+    }
+
+    printf("[LN_MQTT_API] Publishing listen message to topic: %s\n", use_topic);
+    printf("[LN_MQTT_API] Message: %s\n", json_str);
+
+    uint16_t msg_len = (uint16_t)strlen(json_str);
+    int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+
+    cJSON_free(json_str);
+    cJSON_Delete(root);
+
+    if (ret != 0) {
+        printf("[LN_MQTT_API] Failed to queue listen message: %d\n", ret);
+        return -1;
+    }
+
+    printf("[LN_MQTT_API] Listen message queued for sending successfully\n");
+
+    // 发送完成后控制录音:start->开始录音,stop->停止录音
+    if (start) {
+#if USE_DUAL_STREAM_INTERFACE
+        // 使用 old_Start_AIVoice 双流接口(音频已在服务初始化时启动)
+        printf("[LN_MQTT_API] Starting dual stream recording (audio already initialized in service)\n");
+        
+        // 检查 AI 语音服务是否运行(应该在服务初始化时已启动)
+        if (!AI_IsVoiceServiceRunning()) {
+            printf("[LN_MQTT_API] WARNING: AI voice service not running, audio should be initialized in service start\n");
+            return -1;
+        }
+        
+        // 设置录音上传标志位,开始处理并上传音频数据
+        g_recording_upload_started = true;
+        printf("[LN_MQTT_API] Dual stream recording started, upload enabled\n");
+#else
+        // 使用原有 MQTT_StartRecord 接口
+        MqttRecordAudioParams audioParams = {
+            .audioFormat = SBC,        // SBC 格式
+            .channelCount = 1,         // 单声道
+            .sampleRate = 16000         // 16kHz 采样率
+        };
+        
+        int32_t rec_ret = MQTT_StartRecord(ln_mqtt_record_data_cb, NULL, &audioParams);
+        if (rec_ret != 0) {
+            printf("[LN_MQTT_API] WARNING: MQTT_StartRecord failed: %d\n", (int)rec_ret);
+        } else {
+            printf("[LN_MQTT_API] MQTT_StartRecord started with SBC format (16kHz, mono)\n");
+        }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+    } else {
+        // 停止录音前,先刷新缓存中剩余的数据
+        if (g_record_cache.buffer != NULL && g_record_cache.current_size > 0) {
+            printf("[LN_MQTT_API] Flushing remaining cached audio data: %u bytes, %u packets\n",
+                   g_record_cache.current_size, g_record_cache.packet_count);
+            if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+                printf("[LN_MQTT_API] Failed to enqueue remaining cached audio data\n");
+            }
+            g_record_cache.current_size = 0;
+            g_record_cache.packet_count = 0;
+        }
+        // 释放缓存缓冲区
+        if (g_record_cache.buffer != NULL) {
+            free(g_record_cache.buffer);
+            g_record_cache.buffer = NULL;
+            g_record_cache.buffer_size = 0;
+            printf("[LN_MQTT_API] Cache buffer freed\n");
+        }
+        
+#if USE_DUAL_STREAM_INTERFACE
+        // 清除录音上传标志位,停止处理并上传音频数据
+        g_recording_upload_started = false;
+        printf("[LN_MQTT_API] Dual stream recording stopped, upload disabled (AI voice service still running)\n");
+#else
+        // 停止原有 MQTT_StartRecord 接口
+        (void)MQTT_StopRecord();
+#endif /* USE_DUAL_STREAM_INTERFACE */
+    }
+
+    return 0;
+}
+
+
+/**
+ * @brief 获取UDP信息
+ * @param udp_info 输出的UDP信息结构体指针
+ * @return 0 成功(信息有效),-1 失败(信息无效或未设置)
+ */
+int ln_mqtt_api_get_udp_info(ln_mqtt_udp_info_t *udp_info)
+{
+    if (!udp_info) {
+        return -1;
+    }
+    
+    if (!g_udp_info.valid) {
+        printf("[LN_MQTT_API] UDP info not available or invalid\n");
+        return -1;
+    }
+    
+    // 复制UDP信息
+    memcpy(udp_info, &g_udp_info, sizeof(ln_mqtt_udp_info_t));
+    return 0;
+}
+
+// {
+//     "session_id": "3326285112",
+//     "type": "listen",
+//     "state": "start",
+//     "mode": "auto"
+//   }
\ No newline at end of file
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.h b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api.h
new file mode 100644 (file)
index 0000000..277d292
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef LN_MQTT_API_H
+#define LN_MQTT_API_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "uapi_Mqtt_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef USE_DUAL_STREAM_INTERFACE
+#define USE_DUAL_STREAM_INTERFACE 1
+#endif
+
+/**
+ * @brief 启动MQTT服务(启动线程、自动连接等)
+ * @note 启动服务时会自动进行初始化,无需单独调用初始化函数
+ * @note 服务模式下使用内部回调,自动处理连接状态和消息接收
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_start_service(void);
+
+/**
+ * @brief 停止MQTT服务(停止线程、断开连接等)
+ */
+void ln_mqtt_api_stop_service(void);
+
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool ln_mqtt_api_is_connected(void);
+
+/**
+ * @brief 发送MQTT hello消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_hello(void);
+
+/**
+ * @brief 发送 listen 控制消息
+ * @param start true 表示 state=start;false 表示 state=stop
+ * @note session_id 从 hello 消息中解析并在内部保存
+ * @note mode 当前固定发送为 "auto"
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_listen_state(bool start);
+
+/**
+ * @brief UDP信息结构体
+ */
+typedef struct {
+    char server[64];           // UDP服务器地址
+    uint16_t port;             // UDP端口
+    char encryption[32];       // 加密方式
+    char key[64];              // 加密密钥
+    char nonce[64];            // 加密随机数
+    bool valid;                // 信息是否有效
+} ln_mqtt_udp_info_t;
+
+/**
+ * @brief 获取UDP信息
+ * @param udp_info 输出的UDP信息结构体指针
+ * @return 0 成功(信息有效),-1 失败(信息无效或未设置)
+ */
+int ln_mqtt_api_get_udp_info(ln_mqtt_udp_info_t *udp_info);
+
+/**
+ * @brief 初始化MQTT音频服务
+ * @note 只有在MQTT连接时才进行音频初始化
+ */
+void ln_mqtt_audio_init(void);
+
+/**
+ * @brief 反初始化MQTT音频服务
+ */
+void ln_mqtt_audio_deinit(void);
+
+/**
+ * @brief 获取MQTT音频初始化状态
+ * @return true 已初始化,false 未初始化
+ */
+bool ln_mqtt_is_audio_initialized(void);
+
+/**
+ * @brief 初始化音频发送队列和线程(在 ln_UPD.c 中实现)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_init(void);
+
+/**
+ * @brief 停止音频发送线程
+ */
+void ln_udp_audio_send_deinit(void);
+
+/**
+ * @brief 将音频数据放入发送队列(供录音回调函数调用)
+ * @param data 音频数据指针
+ * @param size 音频数据大小
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_MQTT_API_H */
+
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.c
new file mode 100644 (file)
index 0000000..834e2eb
--- /dev/null
@@ -0,0 +1,189 @@
+/*\r
+ * LN MQTT AT test commands\r
+ * - Follow the style in `leiniao_api_at.c` / `uapi_mqtt_at.c`\r
+ * - Provide simple AT commands to drive LN MQTT listen start/stop and hello send\r
+ */\r
+\r
+#include "at_cmd_api.h"\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "errcode.h"\r
+#include "ln_mqtt_api.h"\r
+#include "ln_mqtt_api_at.h"\r
+#include "cmsis_os2.h"\r
+\r
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0]))\r
+#define LN_MQTT_AT_MAX_ARGC 8\r
+#define LN_MQTT_AT_MAX_ARGV_LEN 256\r
+\r
+/* 自动停止定时器(10秒后停止录音) */\r
+static osTimerId_t g_listen_auto_stop_timer = NULL;\r
+\r
+/**\r
+ * @brief 解析AT命令参数\r
+ * 兼容 "AT^XXX=arg1,arg2" 或 "AT^XXX arg1 arg2"\r
+ */\r
+static int ln_mqtt_at_parse_params(uint8_t *para, uint32_t paraLen,\r
+                                  uint8_t argv[LN_MQTT_AT_MAX_ARGC][LN_MQTT_AT_MAX_ARGV_LEN],\r
+                                  uint32_t *argc)\r
+{\r
+    uint32_t pos = 0;\r
+    *argc = 0;\r
+\r
+    for (uint32_t i = 0; i < paraLen; i++) {\r
+        if ((para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') && pos != 0) {\r
+            argv[*argc][pos] = '\0';\r
+            *argc += 1;\r
+            pos = 0;\r
+            if (*argc >= LN_MQTT_AT_MAX_ARGC) {\r
+                return -1;\r
+            }\r
+        } else {\r
+            if (para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') {\r
+                continue;\r
+            }\r
+            argv[*argc][pos] = para[i];\r
+            pos++;\r
+            if (pos >= LN_MQTT_AT_MAX_ARGV_LEN) {\r
+                return -1;\r
+            }\r
+        }\r
+    }\r
+    if (pos != 0) {\r
+        argv[*argc][pos] = '\0';\r
+        *argc += 1;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+/**\r
+ * @brief 自动停止录音的定时器回调函数\r
+ */\r
+static void ln_mqtt_listen_auto_stop_callback(void *arg)\r
+{\r
+    (void)arg;\r
+    printf("[LN_MQTT_AT] Auto stop timer expired, stopping listen...\n");\r
+    (void)ln_mqtt_api_send_listen_state(false);\r
+}\r
+\r
+/* LN MQTT - 发送 listen 控制并开始/停止录音:AT^LN_MQTT_LISTEN=1/0 */\r
+static uint32_t ln_mqtt_listen_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+    (void)strCommonCmd;\r
+\r
+    uint8_t argv[LN_MQTT_AT_MAX_ARGC][LN_MQTT_AT_MAX_ARGV_LEN] = {0};\r
+    uint32_t argc = 0;\r
+    if (ln_mqtt_at_parse_params(para, paraLen, argv, &argc) != 0 || argc < 1) {\r
+        printf("Usage: AT^LN_MQTT_LISTEN=1/0\n");\r
+        return ERRCODE_FAIL;\r
+    }\r
+\r
+    int enable = atoi((char *)argv[0]);\r
+    if (enable != 0 && enable != 1) {\r
+        printf("Usage: AT^LN_MQTT_LISTEN=1/0\n");\r
+        return ERRCODE_FAIL;\r
+    }\r
+\r
+    // 如果之前有定时器在运行,先停止\r
+    if (g_listen_auto_stop_timer != NULL) {\r
+        if (osTimerIsRunning(g_listen_auto_stop_timer) == 1) {\r
+            osTimerStop(g_listen_auto_stop_timer);\r
+        }\r
+    }\r
+\r
+    int ret = ln_mqtt_api_send_listen_state(enable ? true : false);\r
+    if (ret == 0) {\r
+        printf("+LN_MQTT_LISTEN: OK\n");\r
+        \r
+        // 如果 enable == 1,启动10秒后自动停止的定时器\r
+        if (enable == 1) {\r
+            // 如果定时器未创建,先创建\r
+            if (g_listen_auto_stop_timer == NULL) {\r
+                g_listen_auto_stop_timer = osTimerNew((osTimerFunc_t)ln_mqtt_listen_auto_stop_callback, \r
+                                                       osTimerOnce, NULL, NULL);\r
+                if (g_listen_auto_stop_timer == NULL) {\r
+                    printf("[LN_MQTT_AT] WARNING: Failed to create auto stop timer\n");\r
+                }\r
+            }\r
+            \r
+            // 启动定时器(10秒 = 10000毫秒)\r
+            if (g_listen_auto_stop_timer != NULL) {\r
+                osStatus_t timer_ret = osTimerStart(g_listen_auto_stop_timer, 10000);\r
+                if (timer_ret != osOK) {\r
+                    printf("[LN_MQTT_AT] WARNING: Failed to start auto stop timer: %d\n", timer_ret);\r
+                } else {\r
+                    printf("[LN_MQTT_AT] Auto stop timer started (10 seconds)\n");\r
+                }\r
+            }\r
+        }\r
+        \r
+        return ERRCODE_SUCC;\r
+    }\r
+    printf("+LN_MQTT_LISTEN: FAIL\n");\r
+    return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 发送 hello:AT^LN_MQTT_HELLO */\r
+static uint32_t ln_mqtt_hello_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+    (void)para;\r
+    (void)paraLen;\r
+    (void)strCommonCmd;\r
+\r
+    int ret = ln_mqtt_api_send_hello();\r
+    if (ret == 0) {\r
+        printf("+LN_MQTT_HELLO: OK\n");\r
+        return ERRCODE_SUCC;\r
+    }\r
+    printf("+LN_MQTT_HELLO: FAIL\n");\r
+    return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 启动服务:AT^LN_MQTT_START_SERVICE */\r
+static uint32_t ln_mqtt_start_service_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+    (void)para;\r
+    (void)paraLen;\r
+    (void)strCommonCmd;\r
+\r
+    printf("[LN_MQTT_AT] Starting MQTT service...\n");\r
+    int ret = ln_mqtt_api_start_service();\r
+    if (ret == 0) {\r
+        printf("+LN_MQTT_START_SERVICE: OK\n");\r
+        return ERRCODE_SUCC;\r
+    }\r
+    printf("+LN_MQTT_START_SERVICE: FAIL\n");\r
+    return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 停止服务:AT^LN_MQTT_STOP_SERVICE */\r
+static uint32_t ln_mqtt_stop_service_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+    (void)para;\r
+    (void)paraLen;\r
+    (void)strCommonCmd;\r
+\r
+    printf("[LN_MQTT_AT] Stopping MQTT service...\n");\r
+    ln_mqtt_api_stop_service();\r
+    printf("+LN_MQTT_STOP_SERVICE: OK\n");\r
+    return ERRCODE_SUCC;\r
+}\r
+\r
+static const at_cmd_table_t g_ln_mqtt_at_cmds[] = {\r
+    {(char *)"AT^LN_MQTT_LISTEN", ln_mqtt_listen_at, (char *)"LN MQTT listen start/stop: AT^LN_MQTT_LISTEN=1/0"},\r
+    {(char *)"AT^LN_MQTT_HELLO",  ln_mqtt_hello_at,  (char *)"LN MQTT send hello: AT^LN_MQTT_HELLO"},\r
+    {(char *)"AT^LN_MQTT_START_SERVICE", ln_mqtt_start_service_at, (char *)"LN MQTT start service: AT^LN_MQTT_START_SERVICE"},\r
+    {(char *)"AT^LN_MQTT_STOP_SERVICE",  ln_mqtt_stop_service_at,  (char *)"LN MQTT stop service: AT^LN_MQTT_STOP_SERVICE"},\r
+};\r
+\r
+at_cmd_table_t *get_ln_mqtt_at_cmd_table(uint32_t *cmd_count)\r
+{\r
+    if (cmd_count) {\r
+        *cmd_count = ARRAY_COUNT(g_ln_mqtt_at_cmds);\r
+    }\r
+    return (at_cmd_table_t *)g_ln_mqtt_at_cmds;\r
+}\r
+\r
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.h b/code/sdk/zhihui/leiniao/imsl_ln/LN_MQTT/ln_mqtt_api_at.h
new file mode 100644 (file)
index 0000000..b4ceadb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef LN_MQTT_API_AT_H\r
+#define LN_MQTT_API_AT_H\r
+\r
+#include <stdint.h>\r
+#include "at_cmd_api.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* 导出 LN MQTT AT 指令表 */\r
+at_cmd_table_t *get_ln_mqtt_at_cmd_table(uint32_t *cmd_count);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* LN_MQTT_API_AT_H */\r
diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_ota_at.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_ota_at.h
new file mode 100644 (file)
index 0000000..844129a
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef LN_OTA_AT_H
+#define LN_OTA_AT_H
+
+#include <stdint.h>
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* OTA AT 指令表导出 */
+at_cmd_table_t *get_ln_ota_at_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_OTA_AT_H */
+
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/BUILD_LIBOPUS.md b/code/sdk/zhihui/test_opus_frame_to_pcm/BUILD_LIBOPUS.md
new file mode 100644 (file)
index 0000000..4184037
--- /dev/null
@@ -0,0 +1,233 @@
+# 在 test_opus_frame_to_pcm 中构建最小 Opus 解码库\r
+\r
+本文档说明如何在 `test_opus_frame_to_pcm` 目录中从源码直接编译生成最小化的 Opus 解码库 `libopus_min.a`。\r
+\r
+## 概述\r
+\r
+这个构建系统允许你:\r
+1. 只保留解码器必需的源码文件\r
+2. 在 `test_opus_frame_to_pcm` 目录中独立编译\r
+3. 生成一个最小化的 `libopus_min.a` 静态库\r
+4. 验证 `opus_frame_to_pcm` 工具可以正常工作\r
+\r
+## 快速开始\r
+\r
+### 1. 复制必需的源码文件\r
+\r
+运行脚本复制所有必需的源码文件:\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+./copy_sources.sh\r
+```\r
+\r
+这个脚本会:\r
+- 从主项目复制所有解码器相关的 `.c` 文件\r
+- 复制所有必需的头文件 (`.h`)\r
+- 创建必要的目录结构\r
+\r
+### 2. 复制配置文件\r
+\r
+确保 `config.h` 来自主项目(包含正确的编译定义):\r
+\r
+```bash\r
+cp ../config.h config.h\r
+```\r
+\r
+### 3. 复制额外的头文件\r
+\r
+复制一些可能缺失的头文件:\r
+\r
+```bash\r
+# Opus API 头文件\r
+cp ../include/opus_custom.h include/\r
+cp ../include/opus_multistream.h include/\r
+cp ../include/opus_projection.h include/\r
+\r
+# 主项目 src 目录的头文件\r
+find ../src -name '*.h' -exec cp {} src_lib/ \;\r
+\r
+# x86 优化头文件\r
+cp ../celt/x86/*.h celt/x86/ 2>/dev/null || true\r
+cp ../silk/x86/*.h silk/x86/ 2>/dev/null || true\r
+\r
+# SILK 头文件\r
+find ../silk -name '*.h' -exec cp {} silk/ \;\r
+```\r
+\r
+### 4. 编译库\r
+\r
+使用 `Makefile.libopus` 编译:\r
+\r
+```bash\r
+make -f Makefile.libopus\r
+```\r
+\r
+这将:\r
+- 编译所有源文件为 `.o` 对象文件\r
+- 使用 `ar` 创建 `libopus_min.a` 静态库\r
+- 运行 `ranlib` 生成索引\r
+\r
+### 5. 测试\r
+\r
+编译 `opus_frame_to_pcm` 工具并测试:\r
+\r
+```bash\r
+make clean\r
+make\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+```\r
+\r
+## 文件结构\r
+\r
+构建后的目录结构:\r
+\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/          # Opus API 层源码(解码器)\r
+├── celt/             # CELT 解码器源码\r
+│   └── x86/          # CELT x86 优化\r
+├── silk/             # SILK 解码器源码\r
+│   ├── float/        # SILK 浮点实现\r
+│   └── x86/          # SILK x86 优化\r
+├── include/           # Opus 公共头文件\r
+├── config.h          # 编译配置\r
+├── Makefile.libopus  # 库构建 Makefile\r
+├── copy_sources.sh    # 源码复制脚本\r
+└── libopus_min.a     # 生成的静态库\r
+```\r
+\r
+## 包含的源码\r
+\r
+### Opus API 层 (7 个文件)\r
+- `src_lib/opus.c`\r
+- `src_lib/opus_decoder.c`\r
+- `src_lib/opus_multistream_decoder.c`\r
+- `src_lib/opus_projection_decoder.c`\r
+- `src_lib/extensions.c`\r
+- `src_lib/repacketizer.c`\r
+- `src_lib/mapping_matrix.c`\r
+\r
+### CELT 解码器 (~17 个文件)\r
+- 核心解码器文件\r
+- x86 SIMD 优化(SSE, SSE2, SSE4.1, AVX)\r
+\r
+### SILK 解码器 (~70 个文件)\r
+- 核心解码器文件\r
+- 信号处理\r
+- NLSF 处理\r
+- 立体声处理\r
+- 表格数据\r
+- 浮点实现\r
+- x86 优化\r
+\r
+## 编译选项\r
+\r
+`Makefile.libopus` 中的主要编译选项:\r
+\r
+- `-Wall -O2`: 警告和优化级别\r
+- `-DHAVE_CONFIG_H`: 使用 config.h\r
+- `-I. -I./include -I./src_lib -I./celt -I./silk ...`: 包含路径\r
+\r
+特殊处理:\r
+- `celt/x86/pitch_avx.c` 需要 `-mavx2 -mfma` 选项\r
+\r
+## 清理\r
+\r
+### 基本清理\r
+\r
+清理所有编译产物:\r
+\r
+```bash\r
+make -f Makefile.libopus clean\r
+```\r
+\r
+清理所有文件(包括源码):\r
+\r
+```bash\r
+make -f Makefile.libopus distclean\r
+```\r
+\r
+### 完全清理(仅保留源码)\r
+\r
+使用清理脚本清理所有编译产物和中间文件,仅保留源码:\r
+\r
+**Linux/macOS:**\r
+```bash\r
+./clean_all.sh\r
+```\r
+\r
+**Windows PowerShell:**\r
+```powershell\r
+.\clean_all.ps1\r
+```\r
+\r
+**或使用 Makefile:**\r
+```bash\r
+make -f Makefile.libopus cleanall\r
+```\r
+\r
+清理脚本会删除:\r
+- 所有 `.o` 对象文件\r
+- 生成的库文件 (`libopus_min.a`, `libopus.a`)\r
+- 可执行文件 (`opus_frame_to_pcm`)\r
+- 测试输出文件\r
+- Makefile 临时文件\r
+- 备份文件 (`*~`, `*.bak`, `*.swp`, `*.tmp`)\r
+\r
+但会保留:\r
+- 所有源码文件 (`.c`)\r
+- 所有头文件 (`.h`)\r
+- 配置文件 (`config.h`)\r
+- 脚本文件 (`.sh`, `.ps1`, `.bat`)\r
+- Makefile 文件\r
+- 文档文件 (`.md`)\r
+\r
+## 库大小\r
+\r
+生成的 `libopus_min.a` 大小约为 **500-600 KB**(取决于编译选项和优化级别)。\r
+\r
+这比完整的 `libopus.a`(通常 2-3 MB)要小得多,因为:\r
+- 排除了所有编码器代码\r
+- 排除了 DNN/DRED/OSCE 等可选功能\r
+- 只包含解码器必需的代码\r
+\r
+## 故障排除\r
+\r
+### 编译错误:缺少头文件\r
+\r
+确保所有头文件都已复制:\r
+```bash\r
+# 重新复制所有头文件\r
+find ../src -name '*.h' -exec cp {} src_lib/ \;\r
+find ../silk -name '*.h' -exec cp {} silk/ \;\r
+cp ../celt/x86/*.h celt/x86/ 2>/dev/null || true\r
+```\r
+\r
+### 编译错误:AVX 相关\r
+\r
+如果系统不支持 AVX2,可以暂时从 `Makefile.libopus` 中移除 `pitch_avx.c`。\r
+\r
+### 链接错误:未定义符号\r
+\r
+确保 `config.h` 包含正确的定义(特别是 `OPUS_BUILD` 和 `VAR_ARRAYS`)。\r
+\r
+## 验证\r
+\r
+成功构建后,验证库是否正常工作:\r
+\r
+```bash\r
+# 编译工具\r
+make\r
+\r
+# 测试解码\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+\r
+# 检查输出\r
+ls -lh test_output.pcm\r
+```\r
+\r
+如果一切正常,你应该看到:\r
+- 成功编译 `opus_frame_to_pcm`\r
+- 成功解码 Opus 帧\r
+- 生成有效的 PCM 输出文件\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/CLEAN_README.md b/code/sdk/zhihui/test_opus_frame_to_pcm/CLEAN_README.md
new file mode 100644 (file)
index 0000000..170caf6
--- /dev/null
@@ -0,0 +1,124 @@
+# 清理脚本使用说明\r
+\r
+## 概述\r
+\r
+`clean_all.sh` (Linux/macOS) 和 `clean_all.ps1` (Windows PowerShell) 用于清理所有编译产物和中间文件,仅保留源码文件。\r
+\r
+## 使用方法\r
+\r
+### Linux/macOS\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+./clean_all.sh\r
+```\r
+\r
+### Windows PowerShell\r
+\r
+```powershell\r
+cd test_opus_frame_to_pcm\r
+.\clean_all.ps1\r
+```\r
+\r
+### 使用 Makefile\r
+\r
+```bash\r
+make -f Makefile.libopus cleanall\r
+```\r
+\r
+## 清理内容\r
+\r
+脚本会删除以下文件:\r
+\r
+### 编译产物\r
+- 所有 `.o` 对象文件\r
+- 生成的库文件:`libopus_min.a`, `libopus.a` (包括符号链接)\r
+- 可执行文件:`opus_frame_to_pcm`, `opus_frame_to_pcm.exe`\r
+\r
+### 测试文件\r
+- `test_output.pcm`\r
+- `test_output_new.pcm`\r
+- `test_frame.opus`\r
+\r
+### 临时文件\r
+- Makefile 依赖文件 (`.d`)\r
+- 备份文件 (`*~`, `*.bak`, `*.swp`, `*.tmp`)\r
+- 其他临时文件\r
+\r
+## 保留的文件\r
+\r
+清理后,以下文件会被保留:\r
+\r
+- ✅ 所有源码文件 (`.c`)\r
+- ✅ 所有头文件 (`.h`)\r
+- ✅ 配置文件 (`config.h`)\r
+- ✅ 脚本文件 (`.sh`, `.ps1`, `.bat`)\r
+- ✅ Makefile 文件 (`Makefile`, `Makefile.libopus`)\r
+- ✅ 文档文件 (`.md`)\r
+\r
+## 示例\r
+\r
+### 清理前\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/\r
+│   ├── opus.c\r
+│   ├── opus.o          ← 将被删除\r
+│   └── opus_decoder.c\r
+├── libopus_min.a       ← 将被删除\r
+├── opus_frame_to_pcm   ← 将被删除\r
+└── test_output.pcm     ← 将被删除\r
+```\r
+\r
+### 清理后\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/\r
+│   ├── opus.c          ← 保留\r
+│   └── opus_decoder.c  ← 保留\r
+└── (其他源码文件)      ← 保留\r
+```\r
+\r
+## 重新构建\r
+\r
+清理后,可以重新构建:\r
+\r
+```bash\r
+# 1. 确保源码已复制(如果之前已清理源码)\r
+./copy_sources.sh\r
+\r
+# 2. 编译库\r
+make -f Makefile.libopus\r
+\r
+# 3. 编译工具\r
+make\r
+```\r
+\r
+## 注意事项\r
+\r
+1. **清理是不可逆的**:删除的文件无法恢复,请确保已保存重要数据\r
+2. **符号链接**:脚本会正确处理符号链接(如 `libopus.a -> libopus_min.a`)\r
+3. **空目录**:脚本会尝试清理空目录,但会保留源码目录结构\r
+4. **权限**:确保脚本有执行权限(`chmod +x clean_all.sh`)\r
+\r
+## 与其他清理命令的区别\r
+\r
+| 命令 | 清理范围 |\r
+|------|---------|\r
+| `make -f Makefile.libopus clean` | 仅清理 Makefile.libopus 生成的文件 |\r
+| `make clean` | 仅清理主 Makefile 生成的文件 |\r
+| `./clean_all.sh` | **完全清理**:所有编译产物和中间文件 |\r
+| `make -f Makefile.libopus distclean` | 清理所有文件,包括源码目录 |\r
+\r
+## 故障排除\r
+\r
+### 权限错误\r
+```bash\r
+chmod +x clean_all.sh\r
+```\r
+\r
+### 找不到文件\r
+如果某些文件不存在,脚本会跳过,不会报错。\r
+\r
+### 符号链接问题\r
+脚本会自动检测并正确处理符号链接。\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/CMakeLists.txt b/code/sdk/zhihui/test_opus_frame_to_pcm/CMakeLists.txt
new file mode 100644 (file)
index 0000000..60a1d6a
--- /dev/null
@@ -0,0 +1,81 @@
+cmake_minimum_required(VERSION 3.16)
+
+# 设置模块名称
+# 注意:系统链接阶段依赖的是 -lopus_frame_to_pcm_interface
+# build_component() 通常会基于 COMPONENT_NAME 生成 *_interface 库名
+# 因此这里 COMPONENT_NAME 需要为 "opus_frame_to_pcm",以产出 "opus_frame_to_pcm_interface"
+set(COMPONENT_NAME "opus_frame_to_pcm")
+
+# 应用主程序
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/opus_frame_to_pcm.c
+)
+
+# 将 opus 库的 .c 源文件全部链接进来(替代原有静态库)
+file(GLOB OPUS_SRC_LIB "${CMAKE_CURRENT_SOURCE_DIR}/src_lib/*.c")
+file(GLOB OPUS_CELT    "${CMAKE_CURRENT_SOURCE_DIR}/celt/*.c")
+file(GLOB OPUS_SILK    "${CMAKE_CURRENT_SOURCE_DIR}/silk/*.c")
+file(GLOB OPUS_SILK_FLOAT "${CMAKE_CURRENT_SOURCE_DIR}/silk/float/*.c")
+
+# 仅 x86 平台编译 SIMD 优化源;非 x86(如 ARM/Cortex/RISC-V)不包含,使用 C 通用实现
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "[xX]86|i686|AMD64|x86_64")
+  file(GLOB OPUS_CELT_X86  "${CMAKE_CURRENT_SOURCE_DIR}/celt/x86/*.c")
+  file(GLOB OPUS_SILK_X86  "${CMAKE_CURRENT_SOURCE_DIR}/silk/x86/*.c")
+  list(APPEND SOURCES ${OPUS_SRC_LIB} ${OPUS_CELT} ${OPUS_CELT_X86} ${OPUS_SILK} ${OPUS_SILK_FLOAT} ${OPUS_SILK_X86})
+else()
+  # 非 x86 平台:排除 x86 特定的 AVX2 文件
+  list(REMOVE_ITEM OPUS_SILK_FLOAT "${CMAKE_CURRENT_SOURCE_DIR}/silk/float/inner_product_FLP_avx2.c")
+  list(APPEND SOURCES ${OPUS_SRC_LIB} ${OPUS_CELT} ${OPUS_SILK} ${OPUS_SILK_FLOAT})
+endif()
+
+# 头文件目录
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+set(PRIVATE_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/src_lib
+    ${CMAKE_CURRENT_SOURCE_DIR}/silk
+    ${CMAKE_CURRENT_SOURCE_DIR}/silk/float
+    ${CMAKE_CURRENT_SOURCE_DIR}/celt
+)
+
+set(PUBLIC_DEFINES    
+    SUPPORT_OPUS_FRAME_TO_PCM
+    # 非 x86 平台避免引入本目录的 config.h(其包含 x86/RTCD 宏会导致引用 *_sse 等符号)
+    # 如需平台特定优化,可在对应架构下单独打开
+    OPUS_BUILD=1
+    OPUS_HAVE_RTCD=0
+    # 选择 Opus 临时内存分配方式:使用 C99 VLA,避免 pseudostack/ALIGN 冲突
+    VAR_ARRAYS=1
+    # 解决 celt/float_cast.h 在 -Werror 下的 #warning 报错
+    HAVE_LRINT=1
+    HAVE_LRINTF=1
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+# 编译选项
+set(COMPONENT_CCFLAGS
+    -Wall
+    -Wextra
+    -O2
+)
+
+# 是否整体链接
+set(WHOLE_LINK
+    false
+)
+
+# 是否为主组件
+set(MAIN_COMPONENT
+    false
+)
+
+# 构建组件
+build_component()
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/Makefile b/code/sdk/zhihui/test_opus_frame_to_pcm/Makefile
new file mode 100644 (file)
index 0000000..88f4c14
--- /dev/null
@@ -0,0 +1,63 @@
+# Makefile for opus_frame_to_pcm test\r
+# This is a minimal build configuration for testing\r
+\r
+CC = gcc\r
+CFLAGS = -Wall -O2 -I. -I./include -I./src\r
+LDFLAGS = -L. -lopus -lm\r
+\r
+# Source files\r
+SRC_DIR = src\r
+INCLUDE_DIR = include\r
+\r
+# Target executable\r
+TARGET = opus_frame_to_pcm\r
+\r
+# Source file\r
+SOURCES = $(SRC_DIR)/opus_frame_to_pcm.c\r
+\r
+# Object files\r
+OBJECTS = $(SOURCES:.c=.o)\r
+\r
+# Default target\r
+all: $(TARGET)\r
+\r
+# Build executable\r
+LIBOPUS ?= libopus_min.a\r
+\r
+$(TARGET): $(OBJECTS) $(LIBOPUS)\r
+       # Ensure we link against the chosen archive name\r
+       @if [ "$(LIBOPUS)" != "libopus.a" ]; then \\r
+               rm -f libopus.a; \\r
+               ln -s "$(LIBOPUS)" libopus.a; \\r
+       fi\r
+       $(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)\r
+\r
+# Compile source files\r
+$(SRC_DIR)/%.o: $(SRC_DIR)/%.c\r
+       $(CC) $(CFLAGS) -c $< -o $@\r
+\r
+# Check if libopus.a exists\r
+$(LIBOPUS):\r
+       @if [ ! -f $(LIBOPUS) ]; then \\r
+               echo "Error: libopus.a not found!"; \\r
+               echo "Please create $(LIBOPUS) first."; \\r
+               echo "Recommended (PowerShell):"; \\r
+               echo "  ./build_min_libopus.ps1"; \\r
+               echo "Fallback: copy the full libopus.a as $(LIBOPUS) (NOT recommended for size validation)."; \\r
+               exit 1; \\r
+       fi\r
+\r
+# Clean build artifacts\r
+clean:\r
+       rm -f $(OBJECTS) $(TARGET)\r
+\r
+# Test with a sample file (if available)\r
+test: $(TARGET)\r
+       @if [ -f test_frame.opus ]; then \\r
+               ./$(TARGET) test_frame.opus -o test_output.pcm -r 16000 -c 1; \\r
+               echo "Test completed. Check test_output.pcm"; \\r
+       else \\r
+               echo "No test_frame.opus found. Please provide a test file."; \\r
+       fi\r
+\r
+.PHONY: all clean test\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/Makefile.libopus b/code/sdk/zhihui/test_opus_frame_to_pcm/Makefile.libopus
new file mode 100644 (file)
index 0000000..9b16a4b
--- /dev/null
@@ -0,0 +1,252 @@
+# Makefile for building minimal Opus decoder library (libopus_min.a)\r
+# This builds a decoder-only library from source files\r
+\r
+CC = gcc\r
+AR = ar\r
+RANLIB = ranlib\r
+\r
+# Compiler flags\r
+CFLAGS = -Wall -O2 -I. -I./include -I./src_lib -I./celt -I./silk -I./silk/float -I./silk/fixed\r
+CFLAGS += -DHAVE_CONFIG_H -I.\r
+\r
+# Optional: Use fixed-point mode (smaller, but lower quality)\r
+# CFLAGS += -DFIXED_POINT\r
+\r
+# Optional: Disable float API\r
+# CFLAGS += -DDISABLE_FLOAT_API\r
+\r
+# Library name\r
+LIBRARY = libopus_min.a\r
+\r
+# Source directories\r
+SRC_LIB_DIR = src_lib\r
+CELT_DIR = celt\r
+SILK_DIR = silk\r
+\r
+# Opus API layer sources (decoder only)\r
+OPUS_SOURCES = \\r
+       $(SRC_LIB_DIR)/opus.c \\r
+       $(SRC_LIB_DIR)/opus_decoder.c \\r
+       $(SRC_LIB_DIR)/opus_multistream_decoder.c \\r
+       $(SRC_LIB_DIR)/opus_projection_decoder.c \\r
+       $(SRC_LIB_DIR)/extensions.c \\r
+       $(SRC_LIB_DIR)/repacketizer.c \\r
+       $(SRC_LIB_DIR)/mapping_matrix.c\r
+\r
+# CELT decoder sources\r
+CELT_SOURCES = \\r
+       $(CELT_DIR)/bands.c \\r
+       $(CELT_DIR)/celt.c \\r
+       $(CELT_DIR)/celt_decoder.c \\r
+       $(CELT_DIR)/cwrs.c \\r
+       $(CELT_DIR)/entcode.c \\r
+       $(CELT_DIR)/entdec.c \\r
+       $(CELT_DIR)/entenc.c \\r
+       $(CELT_DIR)/kiss_fft.c \\r
+       $(CELT_DIR)/laplace.c \\r
+       $(CELT_DIR)/mathops.c \\r
+       $(CELT_DIR)/mdct.c \\r
+       $(CELT_DIR)/modes.c \\r
+       $(CELT_DIR)/pitch.c \\r
+       $(CELT_DIR)/celt_lpc.c \\r
+       $(CELT_DIR)/quant_bands.c \\r
+       $(CELT_DIR)/rate.c \\r
+       $(CELT_DIR)/vq.c\r
+\r
+# CELT x86 optimization (if available)\r
+CELT_X86_SOURCES = \\r
+       $(CELT_DIR)/x86/x86cpu.c \\r
+       $(CELT_DIR)/x86/x86_celt_map.c \\r
+       $(CELT_DIR)/x86/pitch_sse.c \\r
+       $(CELT_DIR)/x86/pitch_sse2.c \\r
+       $(CELT_DIR)/x86/vq_sse2.c \\r
+       $(CELT_DIR)/x86/celt_lpc_sse4_1.c \\r
+       $(CELT_DIR)/x86/pitch_sse4_1.c \\r
+       $(CELT_DIR)/x86/pitch_avx.c\r
+\r
+# SILK decoder sources (core)\r
+SILK_CORE_SOURCES = \\r
+       $(SILK_DIR)/dec_API.c \\r
+       $(SILK_DIR)/init_decoder.c \\r
+       $(SILK_DIR)/decode_core.c \\r
+       $(SILK_DIR)/decode_frame.c \\r
+       $(SILK_DIR)/decode_parameters.c \\r
+       $(SILK_DIR)/decode_indices.c \\r
+       $(SILK_DIR)/decode_pulses.c \\r
+       $(SILK_DIR)/decoder_set_fs.c\r
+\r
+# SILK signal processing (shared)\r
+SILK_SIGNAL_SOURCES = \\r
+       $(SILK_DIR)/CNG.c \\r
+       $(SILK_DIR)/PLC.c \\r
+       $(SILK_DIR)/resampler.c \\r
+       $(SILK_DIR)/resampler_down2_3.c \\r
+       $(SILK_DIR)/resampler_down2.c \\r
+       $(SILK_DIR)/resampler_private_AR2.c \\r
+       $(SILK_DIR)/resampler_private_down_FIR.c \\r
+       $(SILK_DIR)/resampler_private_IIR_FIR.c \\r
+       $(SILK_DIR)/resampler_private_up2_HQ.c \\r
+       $(SILK_DIR)/resampler_rom.c \\r
+       $(SILK_DIR)/biquad_alt.c \\r
+       $(SILK_DIR)/bwexpander_32.c \\r
+       $(SILK_DIR)/bwexpander.c \\r
+       $(SILK_DIR)/LP_variable_cutoff.c \\r
+       $(SILK_DIR)/HP_variable_cutoff.c\r
+\r
+# SILK NLSF processing\r
+SILK_NLSF_SOURCES = \\r
+       $(SILK_DIR)/NLSF_decode.c \\r
+       $(SILK_DIR)/NLSF_unpack.c \\r
+       $(SILK_DIR)/NLSF2A.c \\r
+       $(SILK_DIR)/NLSF_stabilize.c \\r
+       $(SILK_DIR)/A2NLSF.c \\r
+       $(SILK_DIR)/NLSF_VQ_weights_laroia.c \\r
+       $(SILK_DIR)/table_LSF_cos.c \\r
+       $(SILK_DIR)/LPC_inv_pred_gain.c\r
+\r
+# SILK stereo processing\r
+SILK_STEREO_SOURCES = \\r
+       $(SILK_DIR)/stereo_MS_to_LR.c \\r
+       $(SILK_DIR)/stereo_decode_pred.c \\r
+       $(SILK_DIR)/stereo_find_predictor.c\r
+\r
+# SILK tables\r
+SILK_TABLE_SOURCES = \\r
+       $(SILK_DIR)/tables_gain.c \\r
+       $(SILK_DIR)/tables_LTP.c \\r
+       $(SILK_DIR)/tables_NLSF_CB_NB_MB.c \\r
+       $(SILK_DIR)/tables_NLSF_CB_WB.c \\r
+       $(SILK_DIR)/tables_other.c \\r
+       $(SILK_DIR)/tables_pitch_lag.c \\r
+       $(SILK_DIR)/tables_pulses_per_block.c \\r
+       $(SILK_DIR)/pitch_est_tables.c\r
+\r
+# SILK helper functions\r
+SILK_HELPER_SOURCES = \\r
+       $(SILK_DIR)/code_signs.c \\r
+       $(SILK_DIR)/interpolate.c \\r
+       $(SILK_DIR)/shell_coder.c \\r
+       $(SILK_DIR)/decode_pitch.c \\r
+       $(SILK_DIR)/inner_prod_aligned.c \\r
+       $(SILK_DIR)/lin2log.c \\r
+       $(SILK_DIR)/log2lin.c \\r
+       $(SILK_DIR)/LPC_analysis_filter.c \\r
+       $(SILK_DIR)/LPC_fit.c \\r
+       $(SILK_DIR)/sigm_Q15.c \\r
+       $(SILK_DIR)/sort.c \\r
+       $(SILK_DIR)/sum_sqr_shift.c \\r
+       $(SILK_DIR)/gain_quant.c\r
+\r
+# SILK float implementation (default, comment out if using fixed-point)\r
+SILK_FLOAT_SOURCES = \\r
+       $(SILK_DIR)/float/apply_sine_window_FLP.c \\r
+       $(SILK_DIR)/float/corrMatrix_FLP.c \\r
+       $(SILK_DIR)/float/find_LPC_FLP.c \\r
+       $(SILK_DIR)/float/find_LTP_FLP.c \\r
+       $(SILK_DIR)/float/find_pitch_lags_FLP.c \\r
+       $(SILK_DIR)/float/find_pred_coefs_FLP.c \\r
+       $(SILK_DIR)/float/LPC_analysis_filter_FLP.c \\r
+       $(SILK_DIR)/float/LTP_analysis_filter_FLP.c \\r
+       $(SILK_DIR)/float/LTP_scale_ctrl_FLP.c \\r
+       $(SILK_DIR)/float/noise_shape_analysis_FLP.c \\r
+       $(SILK_DIR)/float/process_gains_FLP.c \\r
+       $(SILK_DIR)/float/regularize_correlations_FLP.c \\r
+       $(SILK_DIR)/float/residual_energy_FLP.c \\r
+       $(SILK_DIR)/float/warped_autocorrelation_FLP.c \\r
+       $(SILK_DIR)/float/wrappers_FLP.c \\r
+       $(SILK_DIR)/float/autocorrelation_FLP.c \\r
+       $(SILK_DIR)/float/burg_modified_FLP.c \\r
+       $(SILK_DIR)/float/bwexpander_FLP.c \\r
+       $(SILK_DIR)/float/energy_FLP.c \\r
+       $(SILK_DIR)/float/inner_product_FLP.c \\r
+       $(SILK_DIR)/float/k2a_FLP.c \\r
+       $(SILK_DIR)/float/LPC_inv_pred_gain_FLP.c \\r
+       $(SILK_DIR)/float/pitch_analysis_core_FLP.c \\r
+       $(SILK_DIR)/float/scale_copy_vector_FLP.c \\r
+       $(SILK_DIR)/float/scale_vector_FLP.c \\r
+       $(SILK_DIR)/float/schur_FLP.c \\r
+       $(SILK_DIR)/float/sort_FLP.c\r
+\r
+# SILK x86 optimization (if available)\r
+SILK_X86_SOURCES = \\r
+       $(SILK_DIR)/x86/x86_silk_map.c\r
+\r
+# Combine all sources\r
+ALL_SOURCES = \\r
+       $(OPUS_SOURCES) \\r
+       $(CELT_SOURCES) \\r
+       $(CELT_X86_SOURCES) \\r
+       $(SILK_CORE_SOURCES) \\r
+       $(SILK_SIGNAL_SOURCES) \\r
+       $(SILK_NLSF_SOURCES) \\r
+       $(SILK_STEREO_SOURCES) \\r
+       $(SILK_TABLE_SOURCES) \\r
+       $(SILK_HELPER_SOURCES) \\r
+       $(SILK_FLOAT_SOURCES) \\r
+       $(SILK_X86_SOURCES)\r
+\r
+# Object files\r
+OBJECTS = $(ALL_SOURCES:.c=.o)\r
+\r
+# Default target\r
+all: $(LIBRARY)\r
+\r
+# Build library\r
+$(LIBRARY): $(OBJECTS)\r
+       @echo "Creating $(LIBRARY)..."\r
+       $(AR) rcs $(LIBRARY) $(OBJECTS)\r
+       $(RANLIB) $(LIBRARY)\r
+       @echo "Library created: $(LIBRARY)"\r
+       @ls -lh $(LIBRARY)\r
+\r
+# Compile source files\r
+%.o: %.c\r
+       @echo "Compiling $<..."\r
+       @mkdir -p $(dir $@)\r
+       $(CC) $(CFLAGS) -c $< -o $@\r
+\r
+# Special handling for AVX files (requires -mavx2 -mfma)\r
+celt/x86/pitch_avx.o: celt/x86/pitch_avx.c\r
+       @echo "Compiling $< (AVX2+FMA)..."\r
+       @mkdir -p $(dir $@)\r
+       $(CC) $(CFLAGS) -mavx2 -mfma -c $< -o $@\r
+\r
+# Check if source files exist\r
+check-sources:\r
+       @echo "Checking source files..."\r
+       @missing=0; \\r
+       for src in $(ALL_SOURCES); do \\r
+               if [ ! -f "$$src" ]; then \\r
+                       echo "Missing: $$src"; \\r
+                       missing=1; \\r
+               fi; \\r
+       done; \\r
+       if [ $$missing -eq 1 ]; then \\r
+               echo "Error: Some source files are missing!"; \\r
+               echo "Please run: ./copy_sources.sh"; \\r
+               exit 1; \\r
+       else \\r
+               echo "All source files present."; \\r
+       fi\r
+\r
+# Clean build artifacts\r
+clean:\r
+       rm -f $(OBJECTS) $(LIBRARY)\r
+       find . -name "*.o" -type f -delete\r
+\r
+# Clean everything including source files\r
+distclean: clean\r
+       rm -rf $(SRC_LIB_DIR) $(CELT_DIR) $(SILK_DIR)\r
+\r
+# Clean all build artifacts and intermediate files (keep source only)\r
+cleanall:\r
+       @echo "Running comprehensive cleanup..."\r
+       @if [ -f "./clean_all.sh" ]; then \\r
+               chmod +x ./clean_all.sh; \\r
+               ./clean_all.sh; \\r
+       else \\r
+               echo "Warning: clean_all.sh not found, using basic clean"; \\r
+               $(MAKE) clean; \\r
+       fi\r
+\r
+.PHONY: all clean distclean cleanall check-sources\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/README.md b/code/sdk/zhihui/test_opus_frame_to_pcm/README.md
new file mode 100644 (file)
index 0000000..531b687
--- /dev/null
@@ -0,0 +1,187 @@
+# Opus Frame to PCM 测试环境\r
+\r
+这是一个用于验证 `opus_frame_to_pcm.c` 功能的独立测试环境。\r
+\r
+## 目录结构\r
+\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src/\r
+│   └── opus_frame_to_pcm.c    # 测试的源代码文件\r
+├── include/\r
+│   ├── opus.h                  # Opus API 头文件\r
+│   ├── opus_defines.h         # Opus 定义\r
+│   └── opus_types.h           # Opus 类型定义\r
+├── libopus.a                  # Opus 静态库(需要从主项目复制)\r
+├── Makefile                   # 构建脚本\r
+└── README.md                  # 本文件\r
+```\r
+\r
+## 依赖要求\r
+\r
+### 必需文件\r
+\r
+1. **libopus.a** - Opus 静态库\r
+   - 可以从主项目的 `.libs/libopus.a` 复制\r
+   - 或者从主项目构建:`cd opus-1.6.1 && make`\r
+\r
+2. **头文件** - 已包含在 `include/` 目录中\r
+\r
+### 系统要求\r
+\r
+- GCC 编译器(或兼容的 C 编译器)\r
+- Make 工具\r
+- 数学库(libm,通常系统自带)\r
+\r
+## 构建步骤\r
+\r
+### 1. 准备库文件\r
+\r
+如果你要验证“删减解码库代码”是否可行,**不要**直接复制主工程的 `libopus.a`。\r
+\r
+推荐创建一个新的 **decoder-only** 静态库:`libopus_min.a`。\r
+\r
+#### 方式 A(Linux/WSL,推荐):生成 libopus_min.a\r
+\r
+先确保主工程已经编译出 `src/*.o`、`celt/*.o`、`silk/*.o`:\r
+\r
+```bash\r
+make\r
+```\r
+\r
+然后生成最小库:\r
+\r
+```bash\r
+./test_opus_frame_to_pcm/build_min_libopus.sh\r
+```\r
+\r
+生成结果:\r
+\r
+- `test_opus_frame_to_pcm/libopus_min.a`\r
+\r
+> Windows 原生 PowerShell 环境如果没有 `ar`(binutils),无法生成 `.a`,建议使用 WSL 或安装 MSYS2/MinGW(带 ar.exe)。\r
+\r
+#### 方式 B(仅验证工具能跑,不验证删减):复制完整 libopus.a\r
+\r
+如果只是想验证 `opus_frame_to_pcm.c` 能编译运行(不关心库是否精简),可以从主项目复制:\r
+\r
+```bash\r
+# 在 opus-1.6.1 目录下\r
+make\r
+cp .libs/libopus.a test_opus_frame_to_pcm/\r
+```\r
+\r
+### 2. 编译\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+make\r
+```\r
+\r
+### 3. 测试\r
+\r
+```bash\r
+# 使用测试文件(如果有)\r
+make test\r
+\r
+# 或手动测试\r
+./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+## 使用方法\r
+\r
+```bash\r
+./opus_frame_to_pcm <input_file> [options]\r
+\r
+选项:\r
+  -o, --output FILE   输出 PCM 文件(默认:标准输出)\r
+  -r, --rate RATE     采样率(Hz,默认:16000)\r
+  -c, --channels N    声道数(默认:1)\r
+  -h, --help          显示帮助信息\r
+```\r
+\r
+## 示例\r
+\r
+```bash\r
+# 基本用法\r
+./opus_frame_to_pcm frame.opus -o output.pcm -r 16000 -c 1\r
+\r
+# 输出到标准输出\r
+./opus_frame_to_pcm frame.opus -r 48000 -c 2 > output.pcm\r
+\r
+# 查看帮助\r
+./opus_frame_to_pcm -h\r
+```\r
+\r
+## 验证功能\r
+\r
+### 1. 编译验证\r
+\r
+```bash\r
+make clean\r
+make\r
+```\r
+\r
+如果编译成功,说明:\r
+- ✅ 源代码语法正确\r
+- ✅ 头文件依赖正确\r
+- ✅ 库文件链接正确\r
+\r
+### 2. 功能验证\r
+\r
+使用一个已知的 Opus 帧文件进行测试:\r
+\r
+```bash\r
+# 如果有测试文件\r
+./opus_frame_to_pcm test_frame.opus -o test.pcm -r 16000 -c 1\r
+\r
+# 检查输出文件\r
+ls -lh test.pcm\r
+file test.pcm\r
+```\r
+\r
+### 3. 输出验证\r
+\r
+PCM 文件应该是:\r
+- 16-bit 小端格式\r
+- 原始 PCM 数据(无头部)\r
+- 文件大小 = 样本数 × 声道数 × 2 字节\r
+\r
+## 故障排除\r
+\r
+### 错误:libopus.a not found\r
+\r
+**解决方法**:\r
+```bash\r
+# 从主项目复制库文件\r
+cp ../.libs/libopus.a .\r
+```\r
+\r
+### 错误:undefined reference to opus_*\r
+\r
+**原因**:库文件不完整或链接错误\r
+\r
+**解决方法**:\r
+1. 确保 `libopus.a` 包含解码器功能\r
+2. 检查链接顺序:`-lopus -lm`\r
+\r
+### 错误:找不到头文件\r
+\r
+**解决方法**:\r
+```bash\r
+# 检查头文件是否存在\r
+ls include/\r
+# 确保 Makefile 中的 -I./include 正确\r
+```\r
+\r
+## 清理\r
+\r
+```bash\r
+make clean\r
+```\r
+\r
+## 注意事项\r
+\r
+1. 这个测试环境只包含最小化的文件,用于验证 `opus_frame_to_pcm.c` 的功能\r
+2. 如果需要完整的 Opus 库功能,请使用主项目的完整构建\r
+3. 测试环境假设使用静态链接,如果需要动态链接,需要修改 Makefile\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/VERIFY.md b/code/sdk/zhihui/test_opus_frame_to_pcm/VERIFY.md
new file mode 100644 (file)
index 0000000..135bf5b
--- /dev/null
@@ -0,0 +1,279 @@
+# 验证步骤说明\r
+\r
+## 一、文件完整性检查\r
+\r
+### 必需文件清单\r
+\r
+✅ **源代码**\r
+- `src/opus_frame_to_pcm.c` - 主程序源代码\r
+\r
+✅ **头文件**\r
+- `include/opus.h` - Opus API 头文件\r
+- `include/opus_defines.h` - Opus 定义\r
+- `include/opus_types.h` - Opus 类型定义\r
+\r
+✅ **库文件**\r
+- `libopus.a` - Opus 静态库(约 5MB)\r
+\r
+✅ **配置文件**\r
+- `config.h` - 最小配置(已创建)\r
+- `Makefile` - 构建脚本(Linux/macOS)\r
+- `build.sh` - 自动构建脚本(Linux/macOS)\r
+- `build.bat` - 自动构建脚本(Windows)\r
+\r
+✅ **文档**\r
+- `README.md` - 使用说明\r
+- `VERIFY.md` - 本文件\r
+\r
+## 二、编译验证\r
+\r
+### Linux/macOS\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+\r
+# 方法1:使用自动构建脚本\r
+chmod +x build.sh\r
+./build.sh\r
+\r
+# 方法2:手动构建\r
+make clean\r
+make\r
+```\r
+\r
+### Windows\r
+\r
+```cmd\r
+cd test_opus_frame_to_pcm\r
+\r
+# 使用批处理脚本\r
+build.bat\r
+\r
+# 或手动编译(需要 MinGW)\r
+gcc -Wall -O2 -I. -I./include -I./src -c src/opus_frame_to_pcm.c -o src/opus_frame_to_pcm.o\r
+gcc src/opus_frame_to_pcm.o -o opus_frame_to_pcm.exe -L. -lopus -lm\r
+```\r
+\r
+### 预期结果\r
+\r
+如果编译成功,应该生成:\r
+- Linux/macOS: `opus_frame_to_pcm` 可执行文件\r
+- Windows: `opus_frame_to_pcm.exe` 可执行文件\r
+\r
+## 三、功能验证\r
+\r
+### 1. 帮助信息测试\r
+\r
+```bash\r
+./opus_frame_to_pcm -h\r
+# 或\r
+./opus_frame_to_pcm --help\r
+```\r
+\r
+**预期输出**:\r
+```\r
+Usage: opus_frame_to_pcm [options] <input_opus_file> [-o output.pcm]\r
+Options:\r
+  -o, --output FILE   Output PCM file (default: stdout)\r
+  -r, --rate RATE    Sample rate in Hz (default: 16000)\r
+  -c, --channels N   Number of channels (default: 1)\r
+  -h, --help         Show this help message\r
+\r
+Example:\r
+  opus_frame_to_pcm frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+### 2. 使用测试文件\r
+\r
+如果有 Opus 帧文件(例如从 `opus_frames_20260128_112654/` 目录):\r
+\r
+```bash\r
+# 复制一个测试文件\r
+cp ../opus_frames_20260128_112654/frame_0001.opus test_frame.opus\r
+\r
+# 运行解码\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+```\r
+\r
+**预期输出**:\r
+```\r
+=== Decoding Opus Frame to PCM ===\r
+Input: test_frame.opus\r
+Output: test_output.pcm\r
+Sample rate: 16000 Hz, Channels: 1\r
+Read XX bytes from input file\r
+Packet info: 1 frame(s), TOC: 0x58\r
+Decoded XXX samples per channel\r
+Total PCM samples: XXX\r
+Saved PCM data to: test_output.pcm\r
+PCM file size: XXX bytes\r
+```\r
+\r
+### 3. 验证输出文件\r
+\r
+```bash\r
+# 检查文件是否存在\r
+ls -lh test_output.pcm\r
+\r
+# 检查文件类型(应该是原始 PCM 数据)\r
+file test_output.pcm\r
+\r
+# 检查文件大小(应该是 样本数 × 声道数 × 2 字节)\r
+# 例如:960 样本 × 1 声道 × 2 = 1920 字节\r
+```\r
+\r
+## 四、常见问题排查\r
+\r
+### 问题1:编译错误 - 找不到 opus.h\r
+\r
+**错误信息**:\r
+```\r
+src/opus_frame_to_pcm.c:37:10: fatal error: opus.h: No such file or directory\r
+```\r
+\r
+**解决方法**:\r
+1. 检查 `include/opus.h` 是否存在\r
+2. 确保 Makefile 中的 `-I./include` 正确\r
+3. 检查当前目录是否正确\r
+\r
+### 问题2:链接错误 - 找不到 libopus.a\r
+\r
+**错误信息**:\r
+```\r
+/usr/bin/ld: cannot find -lopus\r
+```\r
+\r
+**解决方法**:\r
+1. 检查 `libopus.a` 是否存在\r
+2. 确保 Makefile 中的 `-L.` 正确(表示当前目录)\r
+3. 如果库在其他位置,修改 `-L` 路径\r
+\r
+### 问题3:链接错误 - undefined reference\r
+\r
+**错误信息**:\r
+```\r
+undefined reference to `opus_decoder_create'\r
+undefined reference to `opus_decode'\r
+```\r
+\r
+**解决方法**:\r
+1. 确保 `libopus.a` 是完整的库文件\r
+2. 检查库文件是否包含解码器功能\r
+3. 确保链接顺序正确:`-lopus -lm`\r
+\r
+### 问题4:运行时错误 - 无法打开文件\r
+\r
+**错误信息**:\r
+```\r
+Error opening input file: test_frame.opus\r
+```\r
+\r
+**解决方法**:\r
+1. 检查文件路径是否正确\r
+2. 检查文件是否存在\r
+3. 检查文件权限\r
+\r
+### 问题5:运行时错误 - 解析失败\r
+\r
+**错误信息**:\r
+```\r
+Error parsing Opus packet: invalid packet\r
+```\r
+\r
+**解决方法**:\r
+1. 确保输入文件是有效的 Opus 数据包\r
+2. 检查文件是否损坏\r
+3. 尝试使用其他 Opus 帧文件\r
+\r
+## 五、成功标准\r
+\r
+### ✅ 编译成功标准\r
+\r
+1. 无编译错误\r
+2. 无链接错误\r
+3. 生成可执行文件\r
+4. 可执行文件有执行权限(Linux/macOS)\r
+\r
+### ✅ 功能成功标准\r
+\r
+1. 帮助信息正常显示\r
+2. 能够正确解析 Opus 数据包\r
+3. 能够正确解码为 PCM\r
+4. 输出文件格式正确(16-bit 小端 PCM)\r
+5. 输出文件大小符合预期\r
+\r
+## 六、测试用例\r
+\r
+### 测试用例1:基本解码\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -o output1.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出(返回码 0)\r
+- ✅ 输出文件存在\r
+- ✅ 输出文件大小 > 0\r
+\r
+### 测试用例2:不同采样率\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -o output2.pcm -r 48000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出\r
+- ✅ 输出文件存在\r
+- ✅ 文件大小可能不同(取决于实际解码的样本数)\r
+\r
+### 测试用例3:标准输出\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -r 16000 -c 1 > output3.pcm\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出\r
+- ✅ 输出文件存在\r
+- ✅ 文件内容正确\r
+\r
+### 测试用例4:错误处理\r
+\r
+```bash\r
+# 测试不存在的文件\r
+./opus_frame_to_pcm nonexistent.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序返回错误码(非 0)\r
+- ✅ 显示错误信息\r
+- ✅ 不生成输出文件\r
+\r
+## 七、性能验证(可选)\r
+\r
+### 解码速度测试\r
+\r
+```bash\r
+time ./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+### 内存使用测试(Linux)\r
+\r
+```bash\r
+valgrind --leak-check=full ./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 无内存泄漏\r
+- ✅ 无非法内存访问\r
+\r
+## 八、总结\r
+\r
+如果以上所有验证步骤都通过,说明:\r
+\r
+1. ✅ `opus_frame_to_pcm.c` 代码正确\r
+2. ✅ 依赖关系正确\r
+3. ✅ 库文件完整\r
+4. ✅ 功能正常\r
+\r
+可以确认该工具可以在独立环境中正常工作。\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/build.bat b/code/sdk/zhihui/test_opus_frame_to_pcm/build.bat
new file mode 100644 (file)
index 0000000..9070ef2
--- /dev/null
@@ -0,0 +1,54 @@
+@echo off\r
+REM Windows batch script for building opus_frame_to_pcm test\r
+\r
+echo ==========================================\r
+echo Opus Frame to PCM Test Build Script\r
+echo ==========================================\r
+echo.\r
+\r
+REM Check if libopus.a exists\r
+if not exist libopus.a (\r
+    echo Error: libopus.a not found!\r
+    echo Please copy libopus.a from ..\.libs\libopus.a\r
+    echo.\r
+    if exist ..\.libs\libopus.a (\r
+        echo Copying from ..\.libs\libopus.a...\r
+        copy ..\.libs\libopus.a . >nul\r
+        echo Done.\r
+    ) else (\r
+        echo Please build the library first with: make\r
+        exit /b 1\r
+    )\r
+)\r
+\r
+REM Check compiler\r
+where gcc >nul 2>&1\r
+if %errorlevel% neq 0 (\r
+    echo Error: gcc not found in PATH\r
+    echo Please install MinGW or use WSL\r
+    exit /b 1\r
+)\r
+\r
+echo Building...\r
+gcc -Wall -O2 -I. -I./include -I./src -c src/opus_frame_to_pcm.c -o src/opus_frame_to_pcm.o\r
+if %errorlevel% neq 0 (\r
+    echo Compilation failed!\r
+    exit /b 1\r
+)\r
+\r
+gcc src/opus_frame_to_pcm.o -o opus_frame_to_pcm.exe -L. -lopus -lm\r
+if %errorlevel% neq 0 (\r
+    echo Linking failed!\r
+    exit /b 1\r
+)\r
+\r
+echo.\r
+echo ==========================================\r
+echo Build successful!\r
+echo ==========================================\r
+echo.\r
+echo Executable: opus_frame_to_pcm.exe\r
+echo.\r
+echo Usage:\r
+echo   opus_frame_to_pcm.exe input.opus -o output.pcm -r 16000 -c 1\r
+echo.\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/build.sh b/code/sdk/zhihui/test_opus_frame_to_pcm/build.sh
new file mode 100644 (file)
index 0000000..17ecdb9
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/bash
+# 构建脚本 - 自动准备和构建测试环境
+
+set -e
+
+echo "=========================================="
+echo "Opus Frame to PCM 测试环境构建脚本"
+echo "=========================================="
+echo ""
+
+# 检查是否在主项目目录
+if [ ! -f "../src/opus_frame_to_pcm.c" ] && [ ! -f "src/opus_frame_to_pcm.c" ]; then
+    echo "错误:找不到 opus_frame_to_pcm.c"
+    echo "请确保在正确的目录下运行此脚本"
+    exit 1
+fi
+
+# 检查并复制库文件
+if [ ! -f "libopus.a" ]; then
+    echo "正在查找 libopus.a..."
+    
+    # 尝试从主项目的 .libs 目录复制
+    if [ -f "../.libs/libopus.a" ]; then
+        echo "从 ../.libs/libopus.a 复制..."
+        cp ../.libs/libopus.a .
+    elif [ -f "../../.libs/libopus.a" ]; then
+        echo "从 ../../.libs/libopus.a 复制..."
+        cp ../../.libs/libopus.a .
+    else
+        echo "警告:找不到 libopus.a"
+        echo "请先在主项目目录下运行 'make' 构建库"
+        echo "然后手动复制 .libs/libopus.a 到此目录"
+        exit 1
+    fi
+else
+    echo "libopus.a 已存在"
+fi
+
+# 检查库文件大小
+if [ -f "libopus.a" ]; then
+    SIZE=$(stat -c%s libopus.a 2>/dev/null || stat -f%z libopus.a 2>/dev/null)
+    echo "库文件大小: $SIZE 字节"
+fi
+
+# 构建
+echo ""
+echo "开始构建..."
+make clean 2>/dev/null || true
+make
+
+if [ $? -eq 0 ]; then
+    echo ""
+    echo "=========================================="
+    echo "构建成功!"
+    echo "=========================================="
+    echo ""
+    echo "可执行文件: ./opus_frame_to_pcm"
+    echo ""
+    echo "使用方法:"
+    echo "  ./opus_frame_to_pcm <input.opus> -o output.pcm -r 16000 -c 1"
+    echo ""
+else
+    echo ""
+    echo "=========================================="
+    echo "构建失败!"
+    echo "=========================================="
+    exit 1
+fi
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.ps1 b/code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.ps1
new file mode 100644 (file)
index 0000000..7c6ad30
--- /dev/null
@@ -0,0 +1,111 @@
+param(\r
+  [string]$OutDir = "test_opus_frame_to_pcm",\r
+  [string]$OutLib = "libopus_min.a"\r
+)\r
+\r
+$ErrorActionPreference = "Stop"\r
+\r
+function Find-Tool([string[]]$names) {\r
+  foreach ($n in $names) {\r
+    $cmd = Get-Command $n -ErrorAction SilentlyContinue\r
+    if ($cmd) { return $cmd.Path }\r
+  }\r
+  return $null\r
+}\r
+\r
+$ar = Find-Tool @("ar", "llvm-ar")\r
+if (-not $ar) {\r
+  Write-Host "Error: cannot find 'ar' or 'llvm-ar' in PATH."\r
+  Write-Host "This script needs an archiver to create a new .a file."\r
+  exit 1\r
+}\r
+\r
+if (-not (Test-Path $OutDir)) {\r
+  New-Item -ItemType Directory -Path $OutDir -Force | Out-Null\r
+}\r
+\r
+$outPath = Join-Path $OutDir $OutLib\r
+if (Test-Path $outPath) { Remove-Item $outPath -Force }\r
+\r
+# Decoder-only object set:\r
+# - src/: drop *encoder*, analysis/mlp (encoder-side), demos/tools\r
+# - celt/: drop celt_encoder (BUT keep entenc: see note below)\r
+# - silk/: drop encoder-side units\r
+$srcObjs = Get-ChildItem -Path "src" -Filter "*.o" -File | Where-Object {\r
+  $_.Name -notmatch "encoder" -and\r
+  $_.Name -notmatch "^analysis\\.o$" -and\r
+  $_.Name -notmatch "^mlp(_data)?\\.o$" -and\r
+  $_.Name -notmatch "^opus_(demo|compare)\\.o$" -and\r
+  $_.Name -notmatch "^repacketizer_demo\\.o$" -and\r
+  $_.Name -notmatch "^opus_frame_to_pcm\\.o$" -and\r
+  $_.Name -notmatch "^opus_hex_parser\\.o$"\r
+}\r
+\r
+$celtObjs = Get-ChildItem -Path "celt" -Filter "*.o" -File | Where-Object {\r
+  # NOTE: keep entenc.o even for decoder-only validation because several CELT\r
+  # compilation units contain both encoder+decoder code paths in the same .o and\r
+  # will reference ec_enc_* symbols.\r
+  $_.Name -notmatch "celt_encoder\\.o$"\r
+}\r
+\r
+$silkExclude = @(\r
+  "^enc_API\\.o$",\r
+  "^init_encoder\\.o$",\r
+  "^encode_.*\\.o$",\r
+  "^stereo_encode_.*\\.o$",\r
+  "^stereo_quant_.*\\.o$",\r
+  "^stereo_find_predictor\\.o$",\r
+  "^VAD\\.o$",\r
+  "^control_.*\\.o$",\r
+  "^check_control_input\\.o$",\r
+  "^ana_filt_bank_1\\.o$",\r
+  "^NSQ.*\\.o$",\r
+  # gain_quant.o is REQUIRED by the decoder (silk_gains_dequant), so we keep it.\r
+  "^quant_LTP_gains\\.o$",\r
+  "^VQ_WMat_EC\\.o$",\r
+  "^NLSF_encode\\.o$",\r
+  "^NLSF_VQ\\.o$",\r
+  "^NLSF_del_dec_quant\\.o$",\r
+  "^process_NLSFs\\.o$"\r
+)\r
+\r
+$silkObjs = Get-ChildItem -Path "silk" -Filter "*.o" -File | Where-Object {\r
+  $name = $_.Name\r
+  foreach ($re in $silkExclude) {\r
+    if ($name -match $re) { return $false }\r
+  }\r
+  return $true\r
+}\r
+\r
+# RTCD/SIMD dispatch objects:\r
+# If you built with x86 RTCD/SSE, opus_select_arch() and SIMD stubs live under celt/x86 and silk/x86.\r
+$celtX86 = @()\r
+if (Test-Path "celt\\x86") {\r
+  $celtX86 = Get-ChildItem -Path "celt\\x86" -Filter "*.o" -File\r
+}\r
+$silkX86 = @()\r
+if (Test-Path "silk\\x86") {\r
+  $silkX86 = Get-ChildItem -Path "silk\\x86" -Filter "*.o" -File\r
+}\r
+\r
+$all = @($srcObjs + $celtObjs + $celtX86 + $silkObjs + $silkX86)\r
+if ($all.Count -lt 10) {\r
+  Write-Host "Error: too few object files selected ($($all.Count))."\r
+  Write-Host "Make sure you have built the project first so .o files exist."\r
+  exit 1\r
+}\r
+\r
+Write-Host "Using archiver: $ar"\r
+Write-Host "Writing: $outPath"\r
+Write-Host ("Selected objects: src={0}, celt={1}, silk={2}, total={3}" -f $srcObjs.Count, $celtObjs.Count, $silkObjs.Count, $all.Count)\r
+\r
+# Create the new archive\r
+& $ar rcs $outPath @($all.FullName)\r
+\r
+if (-not (Test-Path $outPath)) {\r
+  Write-Host "Error: failed to create $outPath"\r
+  exit 1\r
+}\r
+\r
+$size = (Get-Item $outPath).Length\r
+Write-Host ("Done. {0} created ({1} KB)" -f $OutLib, [math]::Round($size/1KB, 2))\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.sh b/code/sdk/zhihui/test_opus_frame_to_pcm/build_min_libopus.sh
new file mode 100644 (file)
index 0000000..e7ec382
--- /dev/null
@@ -0,0 +1,93 @@
+#!/bin/bash
+# Build a decoder-only libopus_min.a from already-built *.o files in this repo.
+# This is intended to validate code deletion by linking opus_frame_to_pcm against a smaller archive.
+set -euo pipefail
+
+OUT_DIR="${1:-test_opus_frame_to_pcm}"
+OUT_LIB="${2:-libopus_min.a}"
+OUT_PATH="$OUT_DIR/$OUT_LIB"
+
+if ! command -v ar >/dev/null 2>&1; then
+  echo "Error: 'ar' not found. Please install binutils (or use a toolchain that provides ar)." >&2
+  exit 1
+fi
+
+mkdir -p "$OUT_DIR"
+rm -f "$OUT_PATH"
+
+echo "Building $OUT_PATH ..."
+
+# src objects (decoder-side)
+src_objs=()
+while IFS= read -r -d '' f; do src_objs+=("$f"); done < <(find src -maxdepth 1 -name '*.o' -print0)
+
+src_keep=()
+for o in "${src_objs[@]}"; do
+  base="$(basename "$o")"
+  case "$base" in
+    *encoder*.o) continue ;;
+    analysis.o|mlp.o|mlp_data.o) continue ;;
+    opus_demo.o|opus_compare.o|repacketizer_demo.o) continue ;;
+    opus_frame_to_pcm.o|opus_hex_parser.o) continue ;;
+  esac
+  src_keep+=("$o")
+done
+
+# celt objects
+# NOTE: even for decoder-only validation we KEEP entenc.o because several CELT
+# compilation units (e.g. bands/rate/vq) contain both encoder+decoder code paths
+# in the same .o, and will reference ec_enc_* symbols.
+# We still drop celt_encoder.o.
+celt_keep=()
+while IFS= read -r -d '' o; do
+  base="$(basename "$o")"
+  case "$base" in
+    celt_encoder.o) continue ;;
+  esac
+  celt_keep+=("$o")
+done < <(find celt -maxdepth 1 -name '*.o' -print0)
+
+# silk objects (drop encoder-side units)
+silk_keep=()
+while IFS= read -r -d '' o; do
+  base="$(basename "$o")"
+  case "$base" in
+    enc_API.o|init_encoder.o) continue ;;
+    encode_*.o) continue ;;
+    stereo_encode_*.o|stereo_quant_*.o) continue ;;
+    VAD.o) continue ;;
+    control_*.o|check_control_input.o) continue ;;
+    ana_filt_bank_1.o) continue ;;
+    NSQ*.o) continue ;;
+    # gain_quant.o is REQUIRED by the decoder (silk_gains_dequant), so we keep it.
+    quant_LTP_gains.o|VQ_WMat_EC.o) continue ;;
+    NLSF_encode.o|NLSF_VQ.o|NLSF_del_dec_quant.o|process_NLSFs.o) continue ;;
+  esac
+  silk_keep+=("$o")
+done < <(find silk -maxdepth 1 -name '*.o' -print0)
+
+# RTCD/SIMD dispatch objects:
+# opus_select_arch() is provided by arch-specific cpu code when RTCD is enabled.
+# If you built with x86 RTCD/SSE, you must include celt/x86/*.o (and silk/x86 map).
+if [ -d "celt/x86" ]; then
+  while IFS= read -r -d '' o; do
+    # include all built x86 objects (cpu + maps + sse stubs) to satisfy references
+    celt_keep+=("$o")
+  done < <(find celt/x86 -maxdepth 1 -name '*.o' -print0)
+fi
+if [ -d "silk/x86" ]; then
+  while IFS= read -r -d '' o; do
+    silk_keep+=("$o")
+  done < <(find silk/x86 -maxdepth 1 -name '*.o' -print0)
+fi
+
+total=$(( ${#src_keep[@]} + ${#celt_keep[@]} + ${#silk_keep[@]} ))
+echo "Selected objects: src=${#src_keep[@]}, celt=${#celt_keep[@]}, silk=${#silk_keep[@]}, total=$total"
+
+if [ "$total" -lt 10 ]; then
+  echo "Error: too few objects selected ($total). Did you build the main project first (so *.o exist)?" >&2
+  exit 1
+fi
+
+ar rcs "$OUT_PATH" "${src_keep[@]}" "${celt_keep[@]}" "${silk_keep[@]}"
+echo "Done: $(ls -lh "$OUT_PATH")"
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/_kiss_fft_guts.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/_kiss_fft_guts.h
new file mode 100644 (file)
index 0000000..db443c0
--- /dev/null
@@ -0,0 +1,188 @@
+/*Copyright (c) 2003-2004, Mark Borgerding
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.*/
+
+#ifndef KISS_FFT_GUTS_H
+#define KISS_FFT_GUTS_H
+
+#define MIN(a,b) ((a)<(b) ? (a):(b))
+#define MAX(a,b) ((a)>(b) ? (a):(b))
+
+/* kiss_fft.h
+   defines kiss_fft_scalar as either short or a float type
+   and defines
+   typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
+#include "kiss_fft.h"
+
+/*
+  Explanation of macros dealing with complex math:
+
+   C_MUL(m,a,b)         : m = a*b
+   C_FIXDIV( c , div )  : if a fixed point impl., c /= div. noop otherwise
+   C_SUB( res, a,b)     : res = a - b
+   C_SUBFROM( res , a)  : res -= a
+   C_ADDTO( res , a)    : res += a
+ * */
+#ifdef FIXED_POINT
+#include "arch.h"
+
+
+#define SAMP_MAX 2147483647
+#define TWID_MAX 32767
+#define TRIG_UPSCALE 1
+
+#define SAMP_MIN -SAMP_MAX
+
+#ifdef ENABLE_QEXT
+#   define S_MUL(a,b) MULT32_32_P31_ovflw(b, a)
+#   define S_MUL2(a,b) MULT32_32_P31_ovflw(b, a)
+#else
+#   define S_MUL(a,b) MULT16_32_Q15(b, a)
+#   define S_MUL2(a,b) MULT16_32_Q16(b, a)
+#endif
+
+#   define C_MUL(m,a,b) \
+      do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
+
+#   define C_MULC(m,a,b) \
+      do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
+
+#   define C_MULBYSCALAR( c, s ) \
+      do{ (c).r =  S_MUL( (c).r , s ) ;\
+          (c).i =  S_MUL( (c).i , s ) ; }while(0)
+
+#   define DIVSCALAR(x,k) \
+        (x) = S_MUL(  x, (TWID_MAX-((k)>>1))/(k)+1 )
+
+#   define C_FIXDIV(c,div) \
+        do {    DIVSCALAR( (c).r , div);  \
+                DIVSCALAR( (c).i  , div); }while (0)
+
+#define  C_ADD( res, a,b)\
+    do {(res).r=ADD32_ovflw((a).r,(b).r);  (res).i=ADD32_ovflw((a).i,(b).i); \
+    }while(0)
+#define  C_SUB( res, a,b)\
+    do {(res).r=SUB32_ovflw((a).r,(b).r);  (res).i=SUB32_ovflw((a).i,(b).i); \
+    }while(0)
+#define C_ADDTO( res , a)\
+    do {(res).r = ADD32_ovflw((res).r, (a).r);  (res).i = ADD32_ovflw((res).i,(a).i);\
+    }while(0)
+
+#define C_SUBFROM( res , a)\
+    do {(res).r = ADD32_ovflw((res).r,(a).r);  (res).i = SUB32_ovflw((res).i,(a).i); \
+    }while(0)
+
+#if defined(OPUS_ARM_INLINE_ASM)
+#include "arm/kiss_fft_armv4.h"
+#endif
+
+#if defined(OPUS_ARM_INLINE_EDSP)
+#include "arm/kiss_fft_armv5e.h"
+#endif
+#if defined(__mips)
+#include "mips/kiss_fft_mipsr1.h"
+#endif
+
+#else  /* not FIXED_POINT*/
+
+#   define S_MUL(a,b) ( (a)*(b) )
+#   define S_MUL2(a,b) ( (a)*(b) )
+#define C_MUL(m,a,b) \
+    do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
+        (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
+#define C_MULC(m,a,b) \
+    do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
+        (m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
+
+#define C_MUL4(m,a,b) C_MUL(m,a,b)
+
+#   define C_FIXDIV(c,div) /* NOOP */
+#   define C_MULBYSCALAR( c, s ) \
+    do{ (c).r *= (s);\
+        (c).i *= (s); }while(0)
+#endif
+
+#ifndef CHECK_OVERFLOW_OP
+#  define CHECK_OVERFLOW_OP(a,op,b) /* noop */
+#endif
+
+#ifndef C_ADD
+#define  C_ADD( res, a,b)\
+    do { \
+            CHECK_OVERFLOW_OP((a).r,+,(b).r)\
+            CHECK_OVERFLOW_OP((a).i,+,(b).i)\
+            (res).r=(a).r+(b).r;  (res).i=(a).i+(b).i; \
+    }while(0)
+#define  C_SUB( res, a,b)\
+    do { \
+            CHECK_OVERFLOW_OP((a).r,-,(b).r)\
+            CHECK_OVERFLOW_OP((a).i,-,(b).i)\
+            (res).r=(a).r-(b).r;  (res).i=(a).i-(b).i; \
+    }while(0)
+#define C_ADDTO( res , a)\
+    do { \
+            CHECK_OVERFLOW_OP((res).r,+,(a).r)\
+            CHECK_OVERFLOW_OP((res).i,+,(a).i)\
+            (res).r += (a).r;  (res).i += (a).i;\
+    }while(0)
+
+#define C_SUBFROM( res , a)\
+    do {\
+            CHECK_OVERFLOW_OP((res).r,-,(a).r)\
+            CHECK_OVERFLOW_OP((res).i,-,(a).i)\
+            (res).r -= (a).r;  (res).i -= (a).i; \
+    }while(0)
+#endif /* C_ADD defined */
+
+#ifdef FIXED_POINT
+/*#  define KISS_FFT_COS(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
+#  define KISS_FFT_SIN(phase)  TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
+#  define KISS_FFT_COS(phase)  floor(.5+TWID_MAX*cos (phase))
+#  define KISS_FFT_SIN(phase)  floor(.5+TWID_MAX*sin (phase))
+#  define HALF_OF(x) ((x)>>1)
+#elif defined(USE_SIMD)
+#  define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
+#  define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
+#  define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
+#else
+#  define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
+#  define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
+#  define HALF_OF(x) ((x)*.5f)
+#endif
+
+#define  kf_cexp(x,phase) \
+        do{ \
+                (x)->r = KISS_FFT_COS(phase);\
+                (x)->i = KISS_FFT_SIN(phase);\
+        }while(0)
+
+#define  kf_cexp2(x,phase) \
+   do{ \
+      (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
+      (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
+}while(0)
+
+#endif /* KISS_FFT_GUTS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/arch.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/arch.h
new file mode 100644 (file)
index 0000000..63b8ebe
--- /dev/null
@@ -0,0 +1,400 @@
+/* Copyright (c) 2003-2008 Jean-Marc Valin
+   Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/**
+   @file arch.h
+   @brief Various architecture definitions for CELT
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ARCH_H
+#define ARCH_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+# if !defined(__GNUC_PREREQ)
+#  if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+#   define __GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+#  else
+#   define __GNUC_PREREQ(_maj,_min) 0
+#  endif
+# endif
+
+#if OPUS_GNUC_PREREQ(3, 0)
+#define opus_likely(x)       (__builtin_expect(!!(x), 1))
+#define opus_unlikely(x)     (__builtin_expect(!!(x), 0))
+#else
+#define opus_likely(x)       (!!(x))
+#define opus_unlikely(x)     (!!(x))
+#endif
+
+#define CELT_SIG_SCALE 32768.f
+
+#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__)
+
+#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+void celt_fatal(const char *str, const char *file, int line);
+
+#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+void celt_fatal(const char *str, const char *file, int line)
+{
+   fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+#if defined(_MSC_VER)
+   _set_abort_behavior( 0, _WRITE_ABORT_MSG);
+#endif
+   abort();
+}
+#endif
+
+#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
+#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
+#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
+#else
+#define celt_assert(cond) ((void)(cond))
+#define celt_assert2(cond, message) ((void)(cond))
+#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
+#else
+#define celt_sig_assert(cond) ((void)(cond))
+#endif
+
+#define IMUL32(a,b) ((a)*(b))
+
+#define MIN16(a,b) ((a) < (b) ? (a) : (b))   /**< Minimum 16-bit value.   */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b))   /**< Minimum 32-bit value.   */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 32-bit value.   */
+#define IMIN(a,b) ((a) < (b) ? (a) : (b))   /**< Minimum int value.   */
+#define IMAX(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum int value.   */
+#define FMIN(a,b) ((a) < (b) ? (a) : (b))   /**< Minimum float value.   */
+#define FMAX(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum float value.   */
+#define UADD32(a,b) ((a)+(b))
+#define USUB32(a,b) ((a)-(b))
+#define MAXG(a,b) MAX32(a, b)
+#define MING(a,b) MIN32(a, b)
+
+/* Throughout the code, we use the following scaling for signals:
+   FLOAT: used for float API, normalized to +/-1.
+   INT16: used for 16-bit API, normalized to +/- 32768
+   RES: internal Opus resolution, defined as +/-1. in float builds, or either 16-bit or 24-bit int for fixed-point builds
+   SIG: internal CELT resolution: defined as +/- 32768. in float builds, or Q27 in fixed-point builds (int16 shifted by 12)
+*/
+
+
+/* Set this if opus_int64 is a native type of the CPU. */
+/* Assume that all LP64 architectures have fast 64-bit types; also x86_64
+   (which can be ILP32 for x32) and Win64 (which is LLP64). */
+#if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64) || defined (__mips)
+#define OPUS_FAST_INT64 1
+#else
+#define OPUS_FAST_INT64 0
+#endif
+
+#ifdef FIXED_POINT
+#define ARG_FIXED(arg) , arg
+#else
+#define ARG_FIXED(arg)
+#endif
+
+#define PRINT_MIPS(file)
+
+#ifdef FIXED_POINT
+
+typedef opus_int16 opus_val16;
+typedef opus_int32 opus_val32;
+typedef opus_int64 opus_val64;
+
+typedef opus_val32 celt_sig;
+typedef opus_val32 celt_norm;
+typedef opus_val32 celt_ener;
+typedef opus_val32 celt_glog;
+
+#ifdef ENABLE_RES24
+typedef opus_val32 opus_res;
+#define RES_SHIFT 8
+#define SIG2RES(a)      PSHR32(a, SIG_SHIFT-RES_SHIFT)
+#define RES2INT16(a)    SAT16(PSHR32(a, RES_SHIFT))
+#define RES2INT24(a)    (a)
+#define RES2FLOAT(a)    ((1.f/32768.f/256.f)*(a))
+#define INT16TORES(a)   SHL32(EXTEND32(a), RES_SHIFT)
+#define INT24TORES(a)   (a)
+#define ADD_RES(a, b)   ADD32(a, b)
+#define FLOAT2RES(a)    FLOAT2INT24(a)
+#define RES2SIG(a)      SHL32((a), SIG_SHIFT-RES_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_32_Q15(a,b)
+#define MAX_ENCODING_DEPTH 24
+#else
+typedef opus_val16 opus_res;
+#define RES_SHIFT 0
+#define SIG2RES(a)      SIG2WORD16(a)
+#define RES2INT16(a)    (a)
+#define RES2INT24(a)    SHL32(EXTEND32(a), 8)
+#define RES2FLOAT(a)    ((1.f/32768.f)*(a))
+#define INT16TORES(a)   (a)
+#define INT24TORES(a)   SAT16(PSHR32(a, 8))
+#define ADD_RES(a, b)   SAT16(ADD32((a), (b)));
+#define FLOAT2RES(a)    FLOAT2INT16(a)
+#define RES2SIG(a)      SHL32(EXTEND32(a), SIG_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
+#define MAX_ENCODING_DEPTH 16
+#endif
+
+#define RES2VAL16(a)    RES2INT16(a)
+#define INT16TOSIG(a)   SHL32(EXTEND32(a), SIG_SHIFT)
+#define INT24TOSIG(a)   SHL32(a, SIG_SHIFT-8)
+
+#define NORM_SHIFT 24
+#ifdef ENABLE_QEXT
+typedef opus_val32 celt_coef;
+#define COEF_ONE Q31ONE
+#define MULT_COEF_32(a, b) MULT32_32_P31(a,b)
+#define MAC_COEF_32_ARM(c, a, b) ADD32((c), MULT32_32_Q32(a,b))
+#define MULT_COEF(a, b) MULT32_32_Q31(a,b)
+#define MULT_COEF_TAPS(a, b) SHL32(MULT16_16(a,b), 1)
+#define COEF2VAL16(x) EXTRACT16(SHR32(x, 16))
+#else
+typedef opus_val16 celt_coef;
+#define COEF_ONE Q15ONE
+#define MULT_COEF_32(a, b) MULT16_32_Q15(a,b)
+#define MAC_COEF_32_ARM(a, b, c) MAC16_32_Q16(a,b,c)
+#define MULT_COEF(a, b) MULT16_16_Q15(a,b)
+#define MULT_COEF_TAPS(a, b) MULT16_16_P15(a,b)
+#define COEF2VAL16(x) (x)
+#endif
+
+#define celt_isnan(x) 0
+
+#define Q15ONE 32767
+#define Q31ONE 2147483647
+
+#define SIG_SHIFT 12
+/* Safe saturation value for 32-bit signals. We need to make sure that we can
+   add two sig values and that the first stages of the MDCT don't cause an overflow.
+   The most constraining is the ARM_ASM comb filter where we shift left by one
+   and then add two values. Because of that, we use 2^29-1. SIG_SAT must be large
+   enough to fit a full-scale high-freq tone through the prefilter and comb filter,
+   meaning 1.85*1.75*2^(15+SIG_SHIFT) =  434529895.
+   so the limit should be about 2^31*sqrt(.5). */
+#define SIG_SAT (536870911)
+
+#define NORM_SCALING (1<<NORM_SHIFT)
+
+#define DB_SHIFT 24
+
+#define EPSILON 1
+#define VERY_SMALL 0
+#define VERY_LARGE16 ((opus_val16)32767)
+#define Q15_ONE ((opus_val16)32767)
+
+
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))
+
+static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
+   return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x;
+}
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
+#include "arm/fixed_arm64.h"
+#elif defined (OPUS_ARM_INLINE_EDSP)
+#include "arm/fixed_armv5e.h"
+#elif defined (OPUS_ARM_INLINE_ASM)
+#include "arm/fixed_armv4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#elif defined (TI_C5X_ASM)
+#include "fixed_c5x.h"
+#elif defined (TI_C6X_ASM)
+#include "fixed_c6x.h"
+#endif
+
+#endif
+
+#else /* FIXED_POINT */
+
+typedef float opus_val16;
+typedef float opus_val32;
+typedef float opus_val64;
+
+typedef float celt_sig;
+typedef float celt_norm;
+typedef float celt_ener;
+typedef float celt_glog;
+
+typedef float opus_res;
+typedef float celt_coef;
+
+#ifdef FLOAT_APPROX
+/* This code should reliably detect NaN/inf even when -ffast-math is used.
+   Assumes IEEE 754 format. */
+static OPUS_INLINE int celt_isnan(float x)
+{
+   union {float f; opus_uint32 i;} in;
+   in.f = x;
+   return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0;
+}
+#else
+#ifdef __FAST_MATH__
+#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input
+#endif
+#define celt_isnan(x) ((x)!=(x))
+#endif
+
+#define Q15ONE 1.0f
+#define Q31ONE 1.0f
+#define COEF_ONE 1.0f
+#define COEF2VAL16(x) (x)
+
+#define NORM_SCALING 1.f
+
+#define EPSILON 1e-15f
+#define VERY_SMALL 1e-30f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((opus_val16)1.f)
+
+/* This appears to be the same speed as C99's fabsf() but it's more portable. */
+#define ABS16(x) ((float)fabs(x))
+#define ABS32(x) ((float)fabs(x))
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+#define GCONST(x) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define NEG32_ovflw(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+
+#define SHR64(a,shift) (a)
+
+#define PSHR(a,shift)   (a)
+#define SHR(a,shift)    (a)
+#define SHL(a,shift)    (a)
+#define SATURATE(x,a)   (x)
+#define SATURATE16(x)   (x)
+
+#define ROUND16(a,shift)  (a)
+#define SROUND16(a,shift) (a)
+#define HALF16(x)       (.5f*(x))
+#define HALF32(x)       (.5f*(x))
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define ADD32_ovflw(a,b) ((a)+(b))
+#define SUB32_ovflw(a,b) ((a)-(b))
+#define SHL32_ovflw(a,shift) (a)
+#define PSHR32_ovflw(a,shift) (a)
+
+#define MULT16_16_16(a,b)     ((a)*(b))
+#define MULT16_16(a,b)     ((opus_val32)(a)*(opus_val32)(b))
+#define MAC16_16(c,a,b)     ((c)+(opus_val32)(a)*(opus_val32)(b))
+
+#define MULT16_32_Q15(a,b)     ((a)*(b))
+#define MULT16_32_Q16(a,b)     ((a)*(b))
+
+#define MULT32_32_Q16(a,b)     ((a)*(b))
+#define MULT32_32_Q31(a,b)     ((a)*(b))
+#define MULT32_32_P31(a,b)     ((a)*(b))
+#define MULT32_32_P31_ovflw(a,b) ((a)*(b))
+
+#define MAC16_32_Q15(c,a,b)     ((c)+(a)*(b))
+#define MAC16_32_Q16(c,a,b)     ((c)+(a)*(b))
+#define MAC_COEF_32_ARM(c,a,b)     ((c)+(a)*(b))
+
+#define MULT16_16_Q11_32(a,b)     ((a)*(b))
+#define MULT16_16_Q11(a,b)     ((a)*(b))
+#define MULT16_16_Q13(a,b)     ((a)*(b))
+#define MULT16_16_Q14(a,b)     ((a)*(b))
+#define MULT16_16_Q15(a,b)     ((a)*(b))
+#define MULT16_16_P15(a,b)     ((a)*(b))
+#define MULT16_16_P13(a,b)     ((a)*(b))
+#define MULT16_16_P14(a,b)     ((a)*(b))
+#define MULT16_32_P16(a,b)     ((a)*(b))
+
+#define MULT_COEF_32(a, b)      ((a)*(b))
+#define MULT_COEF(a, b)   ((a)*(b))
+#define MULT_COEF_TAPS(a, b)   ((a)*(b))
+
+#define DIV32_16(a,b)     (((opus_val32)(a))/(opus_val16)(b))
+#define DIV32(a,b)     (((opus_val32)(a))/(opus_val32)(b))
+
+#define SIG2RES(a)      ((1/CELT_SIG_SCALE)*(a))
+#define RES2INT16(a)    FLOAT2INT16(a)
+#define RES2INT24(a)    float2int(32768.f*256.f*(a))
+#define RES2FLOAT(a)    (a)
+#define INT16TORES(a)   ((a)*(1/CELT_SIG_SCALE))
+#define INT24TORES(a)   ((1.f/32768.f/256.f)*(a))
+#define ADD_RES(a, b)   ADD32(a, b)
+#define FLOAT2RES(a)    (a)
+#define RES2SIG(a)      (CELT_SIG_SCALE*(a))
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
+
+#define RES2VAL16(a)    (a)
+#define FLOAT2SIG(a)    ((a)*CELT_SIG_SCALE)
+#define INT16TOSIG(a)   ((float)(a))
+#define INT24TOSIG(a)   ((float)(a)*(1.f/256.f))
+#define MAX_ENCODING_DEPTH 24
+
+#endif /* !FIXED_POINT */
+
+#ifndef GLOBAL_STACK_SIZE
+#ifdef FIXED_POINT
+#define GLOBAL_STACK_SIZE 120000
+#else
+#define GLOBAL_STACK_SIZE 120000
+#endif
+#endif
+
+#endif /* ARCH_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.c
new file mode 100644 (file)
index 0000000..afde197
--- /dev/null
@@ -0,0 +1,1922 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008-2009 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "bands.h"
+#include "modes.h"
+#include "vq.h"
+#include "cwrs.h"
+#include "stack_alloc.h"
+#include "os_support.h"
+#include "mathops.h"
+#include "rate.h"
+#include "quant_bands.h"
+#include "pitch.h"
+
+int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev)
+{
+   int i;
+   for (i=0;i<N;i++)
+   {
+      if (val < thresholds[i])
+         break;
+   }
+   if (i>prev && val < thresholds[prev]+hysteresis[prev])
+      i=prev;
+   if (i<prev && val > thresholds[prev-1]-hysteresis[prev-1])
+      i=prev;
+   return i;
+}
+
+opus_uint32 celt_lcg_rand(opus_uint32 seed)
+{
+   return 1664525 * seed + 1013904223;
+}
+
+/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
+   with this approximation is important because it has an impact on the bit allocation */
+opus_int16 bitexact_cos(opus_int16 x)
+{
+   opus_int32 tmp;
+   opus_int16 x2;
+   tmp = (4096+((opus_int32)(x)*(x)))>>13;
+   celt_sig_assert(tmp<=32767);
+   x2 = tmp;
+   x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
+   celt_sig_assert(x2<=32766);
+   return 1+x2;
+}
+
+int bitexact_log2tan(int isin,int icos)
+{
+   int lc;
+   int ls;
+   lc=EC_ILOG(icos);
+   ls=EC_ILOG(isin);
+   icos<<=15-lc;
+   isin<<=15-ls;
+   return (ls-lc)*(1<<11)
+         +FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
+         -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
+}
+
+#ifdef FIXED_POINT
+/* Compute the amplitude (sqrt energy) in each of the bands */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+{
+   int i, c, N;
+   const opus_int16 *eBands = m->eBands;
+   (void)arch;
+   N = m->shortMdctSize<<LM;
+   c=0; do {
+      for (i=0;i<end;i++)
+      {
+         int j;
+         opus_val32 maxval=0;
+         opus_val32 sum = 0;
+
+         maxval = celt_maxabs32(&X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
+         if (maxval > 0)
+         {
+            int shift = IMAX(0, 30 - celt_ilog2(maxval+(maxval>>14)+1) - ((((m->logN[i]+7)>>BITRES)+LM+1)>>1));
+            j=eBands[i]<<LM; do {
+               opus_val32 x = SHL32(X[j+c*N],shift);
+               sum = ADD32(sum, MULT32_32_Q31(x, x));
+            } while (++j<eBands[i+1]<<LM);
+            bandE[i+c*m->nbEBands] = MAX32(maxval, PSHR32(celt_sqrt32(SHR32(sum,1)), shift));
+         } else {
+            bandE[i+c*m->nbEBands] = EPSILON;
+         }
+      }
+   } while (++c<C);
+}
+
+/* Normalise each band such that the energy is one. */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
+{
+   int i, c, N;
+   const opus_int16 *eBands = m->eBands;
+   N = M*m->shortMdctSize;
+   c=0; do {
+      i=0; do {
+         int j,shift;
+         opus_val32 E;
+         opus_val32 g;
+         E = bandE[i+c*m->nbEBands];
+         /* For very low energies, we need this to make sure not to prevent energy rounding from
+            blowing up the normalized signal. */
+         if (E < 10) E += EPSILON;
+         shift = 30-celt_zlog2(E);
+         E = SHL32(E, shift);
+         g = celt_rcp_norm32(E);
+         j=M*eBands[i]; do {
+            X[j+c*N] = PSHR32(MULT32_32_Q31(g, SHL32(freq[j+c*N], shift)), 30-NORM_SHIFT);
+         } while (++j<M*eBands[i+1]);
+      } while (++i<end);
+   } while (++c<C);
+}
+
+#else /* FIXED_POINT */
+/* Compute the amplitude (sqrt energy) in each of the bands */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+{
+   int i, c, N;
+   const opus_int16 *eBands = m->eBands;
+   N = m->shortMdctSize<<LM;
+   c=0; do {
+      for (i=0;i<end;i++)
+      {
+         opus_val32 sum;
+         sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
+         bandE[i+c*m->nbEBands] = celt_sqrt(sum);
+         /*printf ("%f ", bandE[i+c*m->nbEBands]);*/
+      }
+   } while (++c<C);
+   /*printf ("\n");*/
+}
+
+/* Normalise each band such that the energy is one. */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
+{
+   int i, c, N;
+   const opus_int16 *eBands = m->eBands;
+   N = M*m->shortMdctSize;
+   c=0; do {
+      for (i=0;i<end;i++)
+      {
+         int j;
+         opus_val16 g = 1.f/(1e-27f+bandE[i+c*m->nbEBands]);
+         for (j=M*eBands[i];j<M*eBands[i+1];j++)
+            X[j+c*N] = freq[j+c*N]*g;
+      }
+   } while (++c<C);
+}
+
+#endif /* FIXED_POINT */
+
+/* De-normalise the energy to produce the synthesis from the unit-energy bands */
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
+      celt_sig * OPUS_RESTRICT freq, const celt_glog *bandLogE, int start,
+      int end, int M, int downsample, int silence)
+{
+   int i, N;
+   int bound;
+   celt_sig * OPUS_RESTRICT f;
+   const celt_norm * OPUS_RESTRICT x;
+   const opus_int16 *eBands = m->eBands;
+   N = M*m->shortMdctSize;
+   bound = M*eBands[end];
+   if (downsample!=1)
+      bound = IMIN(bound, N/downsample);
+   if (silence)
+   {
+      bound = 0;
+      start = end = 0;
+   }
+   f = freq;
+   x = X+M*eBands[start];
+   if (start != 0)
+   {
+      for (i=0;i<M*eBands[start];i++)
+         *f++ = 0;
+   } else {
+      f += M*eBands[start];
+   }
+   for (i=start;i<end;i++)
+   {
+      int j, band_end;
+      opus_val32 g;
+      celt_glog lg;
+#ifdef FIXED_POINT
+      int shift;
+#endif
+      j=M*eBands[i];
+      band_end = M*eBands[i+1];
+      lg = ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],DB_SHIFT-4));
+#ifndef FIXED_POINT
+      g = celt_exp2_db(MIN32(32.f, lg));
+#else
+      /* Handle the integer part of the log energy */
+      shift = 17-(lg>>DB_SHIFT);
+      if (shift>=31)
+      {
+         shift=0;
+         g=0;
+      } else {
+         /* Handle the fractional part. */
+         g = SHL32(celt_exp2_db_frac((lg&((1<<DB_SHIFT)-1))), 2);
+      }
+      /* Handle extreme gains with negative shift. */
+      if (shift<0)
+      {
+         /* To avoid overflow, we're
+            capping the gain here, which is equivalent to a cap of 18 on lg.
+            This shouldn't trigger unless the bitstream is already corrupted. */
+         g = 2147483647;
+         shift = 0;
+      }
+#endif
+      do {
+         *f++ = PSHR32(MULT32_32_Q31(SHL32(*x, 30-NORM_SHIFT), g), shift);
+         x++;
+      } while (++j<band_end);
+   }
+   celt_assert(start <= end);
+   OPUS_CLEAR(&freq[bound], N-bound);
+}
+
+/* This prevents energy collapse for transients with multiple short MDCTs */
+void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
+      int start, int end, const celt_glog *logE, const celt_glog *prev1logE,
+      const celt_glog *prev2logE, const int *pulses, opus_uint32 seed, int encode, int arch)
+{
+   int c, i, j, k;
+   for (i=start;i<end;i++)
+   {
+      int N0;
+      opus_val16 thresh, sqrt_1;
+      int depth;
+#ifdef FIXED_POINT
+      int shift;
+      opus_val32 thresh32;
+#endif
+
+      N0 = m->eBands[i+1]-m->eBands[i];
+      /* depth in 1/8 bits */
+      celt_sig_assert(pulses[i]>=0);
+      depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM;
+
+#ifdef FIXED_POINT
+      thresh32 = SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1);
+      thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,thresh32));
+      {
+         opus_val32 t;
+         t = N0<<LM;
+         shift = celt_ilog2(t)>>1;
+         t = SHL32(t, (7-shift)<<1);
+         sqrt_1 = celt_rsqrt_norm(t);
+      }
+#else
+      thresh = .5f*celt_exp2(-.125f*depth);
+      sqrt_1 = celt_rsqrt(N0<<LM);
+#endif
+
+      c=0; do
+      {
+         celt_norm *X;
+         celt_glog prev1;
+         celt_glog prev2;
+         opus_val32 Ediff;
+         celt_norm r;
+         int renormalize=0;
+         prev1 = prev1logE[c*m->nbEBands+i];
+         prev2 = prev2logE[c*m->nbEBands+i];
+         if (!encode && C==1)
+         {
+            prev1 = MAXG(prev1,prev1logE[m->nbEBands+i]);
+            prev2 = MAXG(prev2,prev2logE[m->nbEBands+i]);
+         }
+         Ediff = logE[c*m->nbEBands+i]-MING(prev1,prev2);
+         Ediff = MAX32(0, Ediff);
+
+#ifdef FIXED_POINT
+         if (Ediff < GCONST(16.f))
+         {
+            opus_val32 r32 = SHR32(celt_exp2_db(-Ediff),1);
+            r = 2*MIN16(16383,r32);
+         } else {
+            r = 0;
+         }
+         if (LM==3)
+            r = MULT16_16_Q14(23170, MIN32(23169, r));
+         r = SHR16(MIN16(thresh, r),1);
+         r = VSHR32(MULT16_16_Q15(sqrt_1, r),shift+14-NORM_SHIFT);
+#else
+         /* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
+            short blocks don't have the same energy as long */
+         r = 2.f*celt_exp2_db(-Ediff);
+         if (LM==3)
+            r *= 1.41421356f;
+         r = MIN16(thresh, r);
+         r = r*sqrt_1;
+#endif
+         X = X_+c*size+(m->eBands[i]<<LM);
+         for (k=0;k<1<<LM;k++)
+         {
+            /* Detect collapse */
+            if (!(collapse_masks[i*C+c]&1<<k))
+            {
+               /* Fill with noise */
+               for (j=0;j<N0;j++)
+               {
+                  seed = celt_lcg_rand(seed);
+                  X[(j<<LM)+k] = (seed&0x8000 ? r : -r);
+               }
+               renormalize = 1;
+            }
+         }
+         /* We just added some energy, so we need to renormalise */
+         if (renormalize)
+            renormalise_vector(X, N0<<LM, Q31ONE, arch);
+      } while (++c<C);
+   }
+}
+
+/* Compute the weights to use for optimizing normalized distortion across
+   channels. We use the amplitude to weight square distortion, which means
+   that we use the square root of the value we would have been using if we
+   wanted to minimize the MSE in the non-normalized domain. This roughly
+   corresponds to some quick-and-dirty perceptual experiments I ran to
+   measure inter-aural masking (there doesn't seem to be any published data
+   on the topic). */
+static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
+{
+   celt_ener minE;
+#ifdef FIXED_POINT
+   int shift;
+#endif
+   minE = MIN32(Ex, Ey);
+   /* Adjustment to make the weights a bit more conservative. */
+   Ex = ADD32(Ex, minE/3);
+   Ey = ADD32(Ey, minE/3);
+#ifdef FIXED_POINT
+   shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
+#endif
+   w[0] = VSHR32(Ex, shift);
+   w[1] = VSHR32(Ey, shift);
+}
+
+static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
+{
+   int i = bandID;
+   int j;
+   opus_val16 a1, a2;
+   opus_val16 left, right;
+   opus_val16 norm;
+#ifdef FIXED_POINT
+   int shift = celt_zlog2(MAX32(bandE[i], bandE[i+m->nbEBands]))-13;
+#endif
+   left = VSHR32(bandE[i],shift);
+   right = VSHR32(bandE[i+m->nbEBands],shift);
+   norm = EPSILON + celt_sqrt(EPSILON+MULT16_16(left,left)+MULT16_16(right,right));
+#ifdef FIXED_POINT
+   left = MIN32(left, norm-1);
+   right = MIN32(right, norm-1);
+#endif
+   a1 = DIV32_16(SHL32(EXTEND32(left),15),norm);
+   a2 = DIV32_16(SHL32(EXTEND32(right),15),norm);
+   for (j=0;j<N;j++)
+   {
+      X[j] = ADD32(MULT16_32_Q15(a1, X[j]), MULT16_32_Q15(a2, Y[j]));
+      /* Side is not encoded, no need to calculate */
+   }
+}
+
+static void stereo_split(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, int N)
+{
+   int j;
+   for (j=0;j<N;j++)
+   {
+      opus_val32 r, l;
+      l = MULT32_32_Q31(QCONST32(.70710678f,31), X[j]);
+      r = MULT32_32_Q31(QCONST32(.70710678f,31), Y[j]);
+      X[j] = ADD32(l, r);
+      Y[j] = SUB32(r, l);
+   }
+}
+
+static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val32 mid, int N, int arch)
+{
+   int j;
+   opus_val32 xp=0, side=0;
+   opus_val32 El, Er;
+#ifdef FIXED_POINT
+   int kl, kr;
+#endif
+   opus_val32 t, lgain, rgain;
+
+   /* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
+   xp = celt_inner_prod_norm_shift(Y, X, N, arch);
+   side = celt_inner_prod_norm_shift(Y, Y, N, arch);
+   /* Compensating for the mid normalization */
+   xp = MULT32_32_Q31(mid, xp);
+   /* mid and side are in Q15, not Q14 like X and Y */
+   El = SHR32(MULT32_32_Q31(mid, mid),3) + side - 2*xp;
+   Er = SHR32(MULT32_32_Q31(mid, mid),3) + side + 2*xp;
+   if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28))
+   {
+      OPUS_COPY(Y, X, N);
+      return;
+   }
+
+#ifdef FIXED_POINT
+   kl = celt_ilog2(El)>>1;
+   kr = celt_ilog2(Er)>>1;
+#endif
+   t = VSHR32(El, (kl<<1)-29);
+   lgain = celt_rsqrt_norm32(t);
+   t = VSHR32(Er, (kr<<1)-29);
+   rgain = celt_rsqrt_norm32(t);
+
+#ifdef FIXED_POINT
+   if (kl < 7)
+      kl = 7;
+   if (kr < 7)
+      kr = 7;
+#endif
+
+   for (j=0;j<N;j++)
+   {
+      celt_norm r, l;
+      /* Apply mid scaling (side is already scaled) */
+      l = MULT32_32_Q31(mid, X[j]);
+      r = Y[j];
+      X[j] = VSHR32(MULT32_32_Q31(lgain, SUB32(l,r)), kl-15);
+      Y[j] = VSHR32(MULT32_32_Q31(rgain, ADD32(l,r)), kr-15);
+   }
+}
+
+/* Decide whether we should spread the pulses in the current frame */
+int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
+      int last_decision, int *hf_average, int *tapset_decision, int update_hf,
+      int end, int C, int M, const int *spread_weight)
+{
+   int i, c, N0;
+   int sum = 0, nbBands=0;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   int decision;
+   int hf_sum=0;
+
+   celt_assert(end>0);
+
+   N0 = M*m->shortMdctSize;
+
+   if (M*(eBands[end]-eBands[end-1]) <= 8)
+      return SPREAD_NONE;
+   c=0; do {
+      for (i=0;i<end;i++)
+      {
+         int j, N, tmp=0;
+         int tcount[3] = {0,0,0};
+         const celt_norm * OPUS_RESTRICT x = X+M*eBands[i]+c*N0;
+         N = M*(eBands[i+1]-eBands[i]);
+         if (N<=8)
+            continue;
+         /* Compute rough CDF of |x[j]| */
+         for (j=0;j<N;j++)
+         {
+            opus_val32 x2N; /* Q13 */
+
+            x2N = MULT16_16(MULT16_16_Q15(SHR32(x[j], NORM_SHIFT-14), SHR32(x[j], NORM_SHIFT-14)), N);
+            if (x2N < QCONST16(0.25f,13))
+               tcount[0]++;
+            if (x2N < QCONST16(0.0625f,13))
+               tcount[1]++;
+            if (x2N < QCONST16(0.015625f,13))
+               tcount[2]++;
+         }
+
+         /* Only include four last bands (8 kHz and up) */
+         if (i>m->nbEBands-4)
+            hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N);
+         tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N);
+         sum += tmp*spread_weight[i];
+         nbBands+=spread_weight[i];
+      }
+   } while (++c<C);
+
+   if (update_hf)
+   {
+      if (hf_sum)
+         hf_sum = celt_udiv(hf_sum, C*(4-m->nbEBands+end));
+      *hf_average = (*hf_average+hf_sum)>>1;
+      hf_sum = *hf_average;
+      if (*tapset_decision==2)
+         hf_sum += 4;
+      else if (*tapset_decision==0)
+         hf_sum -= 4;
+      if (hf_sum > 22)
+         *tapset_decision=2;
+      else if (hf_sum > 18)
+         *tapset_decision=1;
+      else
+         *tapset_decision=0;
+   }
+   /*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
+   celt_assert(nbBands>0); /* end has to be non-zero */
+   celt_assert(sum>=0);
+   sum = celt_udiv((opus_int32)sum<<8, nbBands);
+   /* Recursive averaging */
+   sum = (sum+*average)>>1;
+   *average = sum;
+   /* Hysteresis */
+   sum = (3*sum + (((3-last_decision)<<7) + 64) + 2)>>2;
+   if (sum < 80)
+   {
+      decision = SPREAD_AGGRESSIVE;
+   } else if (sum < 256)
+   {
+      decision = SPREAD_NORMAL;
+   } else if (sum < 384)
+   {
+      decision = SPREAD_LIGHT;
+   } else {
+      decision = SPREAD_NONE;
+   }
+#ifdef FUZZING
+   decision = rand()&0x3;
+   *tapset_decision=rand()%3;
+#endif
+   return decision;
+}
+
+/* Indexing table for converting from natural Hadamard to ordery Hadamard
+   This is essentially a bit-reversed Gray, on top of which we've added
+   an inversion of the order because we want the DC at the end rather than
+   the beginning. The lines are for N=2, 4, 8, 16 */
+static const int ordery_table[] = {
+       1,  0,
+       3,  0,  2,  1,
+       7,  0,  4,  3,  6,  1,  5,  2,
+      15,  0,  8,  7, 12,  3, 11,  4, 14,  1,  9,  6, 13,  2, 10,  5,
+};
+
+static void deinterleave_hadamard(celt_norm *X, int N0, int stride, int hadamard)
+{
+   int i,j;
+   VARDECL(celt_norm, tmp);
+   int N;
+   SAVE_STACK;
+   N = N0*stride;
+   ALLOC(tmp, N, celt_norm);
+   celt_assert(stride>0);
+   if (hadamard)
+   {
+      const int *ordery = ordery_table+stride-2;
+      for (i=0;i<stride;i++)
+      {
+         for (j=0;j<N0;j++)
+            tmp[ordery[i]*N0+j] = X[j*stride+i];
+      }
+   } else {
+      for (i=0;i<stride;i++)
+         for (j=0;j<N0;j++)
+            tmp[i*N0+j] = X[j*stride+i];
+   }
+   OPUS_COPY(X, tmp, N);
+   RESTORE_STACK;
+}
+
+static void interleave_hadamard(celt_norm *X, int N0, int stride, int hadamard)
+{
+   int i,j;
+   VARDECL(celt_norm, tmp);
+   int N;
+   SAVE_STACK;
+   N = N0*stride;
+   ALLOC(tmp, N, celt_norm);
+   if (hadamard)
+   {
+      const int *ordery = ordery_table+stride-2;
+      for (i=0;i<stride;i++)
+         for (j=0;j<N0;j++)
+            tmp[j*stride+i] = X[ordery[i]*N0+j];
+   } else {
+      for (i=0;i<stride;i++)
+         for (j=0;j<N0;j++)
+            tmp[j*stride+i] = X[i*N0+j];
+   }
+   OPUS_COPY(X, tmp, N);
+   RESTORE_STACK;
+}
+
+void haar1(celt_norm *X, int N0, int stride)
+{
+   int i, j;
+   N0 >>= 1;
+   for (i=0;i<stride;i++)
+      for (j=0;j<N0;j++)
+      {
+         opus_val32 tmp1, tmp2;
+         tmp1 = MULT32_32_Q31(QCONST32(.70710678f,31), X[stride*2*j+i]);
+         tmp2 = MULT32_32_Q31(QCONST32(.70710678f,31), X[stride*(2*j+1)+i]);
+         X[stride*2*j+i] = ADD32(tmp1, tmp2);
+         X[stride*(2*j+1)+i] = SUB32(tmp1, tmp2);
+      }
+}
+
+static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
+{
+   static const opus_int16 exp2_table8[8] =
+      {16384, 17866, 19483, 21247, 23170, 25267, 27554, 30048};
+   int qn, qb;
+   int N2 = 2*N-1;
+   if (stereo && N==2)
+      N2--;
+   /* The upper limit ensures that in a stereo split with itheta==16384, we'll
+       always have enough bits left over to code at least one pulse in the
+       side; otherwise it would collapse, since it doesn't get folded. */
+   qb = celt_sudiv(b+N2*offset, N2);
+   qb = IMIN(b-pulse_cap-(4<<BITRES), qb);
+
+   qb = IMIN(8<<BITRES, qb);
+
+   if (qb<(1<<BITRES>>1)) {
+      qn = 1;
+   } else {
+      qn = exp2_table8[qb&0x7]>>(14-(qb>>BITRES));
+      qn = (qn+1)>>1<<1;
+   }
+   celt_assert(qn <= 256);
+   return qn;
+}
+
+struct band_ctx {
+   int encode;
+   int resynth;
+   const CELTMode *m;
+   int i;
+   int intensity;
+   int spread;
+   int tf_change;
+   ec_ctx *ec;
+   opus_int32 remaining_bits;
+   const celt_ener *bandE;
+   opus_uint32 seed;
+   int arch;
+   int theta_round;
+   int disable_inv;
+   int avoid_split_noise;
+#ifdef ENABLE_QEXT
+   ec_ctx *ext_ec;
+   int extra_bits;
+   opus_int32 ext_total_bits;
+   int extra_bands;
+#endif
+};
+
+struct split_ctx {
+   int inv;
+   int imid;
+   int iside;
+   int delta;
+   int itheta;
+#ifdef ENABLE_QEXT
+   int itheta_q30;
+#endif
+   int qalloc;
+};
+
+static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
+      celt_norm *X, celt_norm *Y, int N, int *b, int B, int B0,
+      int LM,
+      int stereo, int *fill ARG_QEXT(int *ext_b))
+{
+   int qn;
+   int itheta=0;
+   int itheta_q30=0;
+   int delta;
+   int imid, iside;
+   int qalloc;
+   int pulse_cap;
+   int offset;
+   opus_int32 tell;
+   int inv=0;
+   int encode;
+   const CELTMode *m;
+   int i;
+   int intensity;
+   ec_ctx *ec;
+   const celt_ener *bandE;
+
+   encode = ctx->encode;
+   m = ctx->m;
+   i = ctx->i;
+   intensity = ctx->intensity;
+   ec = ctx->ec;
+   bandE = ctx->bandE;
+
+   /* Decide on the resolution to give to the split parameter theta */
+   pulse_cap = m->logN[i]+LM*(1<<BITRES);
+   offset = (pulse_cap>>1) - (stereo&&N==2 ? QTHETA_OFFSET_TWOPHASE : QTHETA_OFFSET);
+   qn = compute_qn(N, *b, offset, pulse_cap, stereo);
+   if (stereo && i>=intensity)
+      qn = 1;
+   if (encode)
+   {
+      /* theta is the atan() of the ratio between the (normalized)
+         side and mid. With just that parameter, we can re-scale both
+         mid and side because we know that 1) they have unit norm and
+         2) they are orthogonal. */
+      itheta_q30 = stereo_itheta(X, Y, stereo, N, ctx->arch);
+      itheta = itheta_q30>>16;
+   }
+   tell = ec_tell_frac(ec);
+   if (qn!=1)
+   {
+      if (encode)
+      {
+         if (!stereo || ctx->theta_round == 0)
+         {
+            itheta = (itheta*(opus_int32)qn+8192)>>14;
+            if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
+            {
+               /* Check if the selected value of theta will cause the bit allocation
+                  to inject noise on one side. If so, make sure the energy of that side
+                  is zero. */
+               int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
+               imid = bitexact_cos((opus_int16)unquantized);
+               iside = bitexact_cos((opus_int16)(16384-unquantized));
+               delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+               if (delta > *b)
+                  itheta = qn;
+               else if (delta < -*b)
+                  itheta = 0;
+            }
+         } else {
+            int down;
+            /* Bias quantization towards itheta=0 and itheta=16384. */
+            int bias = itheta > 8192 ? 32767/qn : -32767/qn;
+            down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
+            if (ctx->theta_round < 0)
+               itheta = down;
+            else
+               itheta = down+1;
+         }
+      }
+      /* Entropy coding of the angle. We use a uniform pdf for the
+         time split, a step for stereo, and a triangular one for the rest. */
+      if (stereo && N>2)
+      {
+         int p0 = 3;
+         int x = itheta;
+         int x0 = qn/2;
+         int ft = p0*(x0+1) + x0;
+         /* Use a probability of p0 up to itheta=8192 and then use 1 after */
+         if (encode)
+         {
+            ec_encode(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft);
+         } else {
+            int fs;
+            fs=ec_decode(ec,ft);
+            if (fs<(x0+1)*p0)
+               x=fs/p0;
+            else
+               x=x0+1+(fs-(x0+1)*p0);
+            ec_dec_update(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft);
+            itheta = x;
+         }
+      } else if (B0>1 || stereo) {
+         /* Uniform pdf */
+         if (encode)
+            ec_enc_uint(ec, itheta, qn+1);
+         else
+            itheta = ec_dec_uint(ec, qn+1);
+      } else {
+         int fs=1, ft;
+         ft = ((qn>>1)+1)*((qn>>1)+1);
+         if (encode)
+         {
+            int fl;
+
+            fs = itheta <= (qn>>1) ? itheta + 1 : qn + 1 - itheta;
+            fl = itheta <= (qn>>1) ? itheta*(itheta + 1)>>1 :
+             ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1);
+
+            ec_encode(ec, fl, fl+fs, ft);
+         } else {
+            /* Triangular pdf */
+            int fl=0;
+            int fm;
+            fm = ec_decode(ec, ft);
+
+            if (fm < ((qn>>1)*((qn>>1) + 1)>>1))
+            {
+               itheta = (isqrt32(8*(opus_uint32)fm + 1) - 1)>>1;
+               fs = itheta + 1;
+               fl = itheta*(itheta + 1)>>1;
+            }
+            else
+            {
+               itheta = (2*(qn + 1)
+                - isqrt32(8*(opus_uint32)(ft - fm - 1) + 1))>>1;
+               fs = qn + 1 - itheta;
+               fl = ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1);
+            }
+
+            ec_dec_update(ec, fl, fl+fs, ft);
+         }
+      }
+      celt_assert(itheta>=0);
+      itheta = celt_udiv((opus_int32)itheta*16384, qn);
+#ifdef ENABLE_QEXT
+      *ext_b = IMIN(*ext_b, ctx->ext_total_bits - (opus_int32)ec_tell_frac(ctx->ext_ec));
+      if (*ext_b >= 2*N<<BITRES && ctx->ext_total_bits-ec_tell_frac(ctx->ext_ec)-1 > 2<<BITRES) {
+         int extra_bits;
+         int ext_tell = ec_tell_frac(ctx->ext_ec);
+         extra_bits = IMIN(12, IMAX(2, celt_sudiv(*ext_b, (2*N-1)<<BITRES)));
+         if (encode) {
+            itheta_q30 = itheta_q30 - (itheta<<16);
+            itheta_q30 = (itheta_q30*(opus_int64)qn*((1<<extra_bits)-1)+(1<<29))>>30;
+            itheta_q30 += (1<<(extra_bits-1))-1;
+            itheta_q30 = IMAX(0, IMIN((1<<extra_bits)-2, itheta_q30));
+            ec_enc_uint(ctx->ext_ec, itheta_q30, (1<<extra_bits)-1);
+         } else {
+            itheta_q30 = ec_dec_uint(ctx->ext_ec, (1<<extra_bits)-1);
+         }
+         itheta_q30 -= (1<<(extra_bits-1))-1;
+         itheta_q30 = (itheta<<16) + itheta_q30*(opus_int64)(1<<30)/(qn*((1<<extra_bits)-1));
+         /* Hard bounds on itheta (can only trigger on corrupted bitstreams). */
+         itheta_q30 = IMAX(0, IMIN(itheta_q30, 1073741824));
+         *ext_b -= ec_tell_frac(ctx->ext_ec) - ext_tell;
+      } else {
+         itheta_q30 = (opus_int32)itheta<<16;
+      }
+#endif
+      if (encode && stereo)
+      {
+         if (itheta==0)
+            intensity_stereo(m, X, Y, bandE, i, N);
+         else
+            stereo_split(X, Y, N);
+      }
+      /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate.
+               Let's do that at higher complexity */
+   } else if (stereo) {
+      if (encode)
+      {
+         inv = itheta > 8192 && !ctx->disable_inv;
+         if (inv)
+         {
+            int j;
+            for (j=0;j<N;j++)
+               Y[j] = -Y[j];
+         }
+         intensity_stereo(m, X, Y, bandE, i, N);
+      }
+      if (*b>2<<BITRES && ctx->remaining_bits > 2<<BITRES)
+      {
+         if (encode)
+            ec_enc_bit_logp(ec, inv, 2);
+         else
+            inv = ec_dec_bit_logp(ec, 2);
+      } else
+         inv = 0;
+      /* inv flag override to avoid problems with downmixing. */
+      if (ctx->disable_inv)
+         inv = 0;
+      itheta = 0;
+      itheta_q30 = 0;
+   }
+   qalloc = ec_tell_frac(ec) - tell;
+   *b -= qalloc;
+
+   if (itheta == 0)
+   {
+      imid = 32767;
+      iside = 0;
+      *fill &= (1<<B)-1;
+      delta = -16384;
+   } else if (itheta == 16384)
+   {
+      imid = 0;
+      iside = 32767;
+      *fill &= ((1<<B)-1)<<B;
+      delta = 16384;
+   } else {
+      imid = bitexact_cos((opus_int16)itheta);
+      iside = bitexact_cos((opus_int16)(16384-itheta));
+      /* This is the mid vs side allocation that minimizes squared error
+         in that band. */
+      delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+   }
+
+   sctx->inv = inv;
+   sctx->imid = imid;
+   sctx->iside = iside;
+   sctx->delta = delta;
+   sctx->itheta = itheta;
+#ifdef ENABLE_QEXT
+   sctx->itheta_q30 = itheta_q30;
+#endif
+   sctx->qalloc = qalloc;
+}
+static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
+      celt_norm *lowband_out)
+{
+   int c;
+   int stereo;
+   celt_norm *x = X;
+   int encode;
+   ec_ctx *ec;
+
+   encode = ctx->encode;
+   ec = ctx->ec;
+
+   stereo = Y != NULL;
+   c=0; do {
+      int sign=0;
+      if (ctx->remaining_bits>=1<<BITRES)
+      {
+         if (encode)
+         {
+            sign = x[0]<0;
+            ec_enc_bits(ec, sign, 1);
+         } else {
+            sign = ec_dec_bits(ec, 1);
+         }
+         ctx->remaining_bits -= 1<<BITRES;
+      }
+      if (ctx->resynth)
+         x[0] = sign ? -NORM_SCALING : NORM_SCALING;
+      x = Y;
+   } while (++c<1+stereo);
+   if (lowband_out)
+      lowband_out[0] = SHR32(X[0],4);
+   return 1;
+}
+
+/* This function is responsible for encoding and decoding a mono partition.
+   It can split the band in two and transmit the energy difference with
+   the two half-bands. It can be called recursively so bands can end up being
+   split in 8 parts. */
+static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
+      int N, int b, int B, celt_norm *lowband,
+      int LM,
+      opus_val32 gain, int fill
+      ARG_QEXT(int ext_b))
+{
+   const unsigned char *cache;
+   int q;
+   int curr_bits;
+   int imid=0, iside=0;
+   int B0=B;
+   opus_val32 mid=0, side=0;
+   unsigned cm=0;
+   celt_norm *Y=NULL;
+   int encode;
+   const CELTMode *m;
+   int i;
+   int spread;
+   ec_ctx *ec;
+
+   encode = ctx->encode;
+   m = ctx->m;
+   i = ctx->i;
+   spread = ctx->spread;
+   ec = ctx->ec;
+
+   /* If we need 1.5 more bit than we can produce, split the band in two. */
+   cache = m->cache.bits + m->cache.index[(LM+1)*m->nbEBands+i];
+   if (LM != -1 && b > cache[cache[0]]+12 && N>2)
+   {
+      int mbits, sbits, delta;
+      int itheta;
+      int qalloc;
+      struct split_ctx sctx;
+      celt_norm *next_lowband2=NULL;
+      opus_int32 rebalance;
+
+      N >>= 1;
+      Y = X+N;
+      LM -= 1;
+      if (B==1)
+         fill = (fill&1)|(fill<<1);
+      B = (B+1)>>1;
+
+      compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill ARG_QEXT(&ext_b));
+      imid = sctx.imid;
+      iside = sctx.iside;
+      delta = sctx.delta;
+      itheta = sctx.itheta;
+      qalloc = sctx.qalloc;
+#ifdef FIXED_POINT
+# ifdef ENABLE_QEXT
+      (void)imid;
+      (void)iside;
+      mid = celt_cos_norm32(sctx.itheta_q30);
+      side = celt_cos_norm32((1<<30)-sctx.itheta_q30);
+# else
+      mid = SHL32(EXTEND32(imid), 16);
+      side = SHL32(EXTEND32(iside), 16);
+# endif
+#else
+# ifdef ENABLE_QEXT
+      (void)imid;
+      (void)iside;
+      mid = celt_cos_norm2(sctx.itheta_q30*(1.f/(1<<30)));
+      side = celt_cos_norm2(1.f-sctx.itheta_q30*(1.f/(1<<30)));
+# else
+      mid = (1.f/32768)*imid;
+      side = (1.f/32768)*iside;
+# endif
+#endif
+
+      /* Give more bits to low-energy MDCTs than they would otherwise deserve */
+      if (B0>1 && (itheta&0x3fff))
+      {
+         if (itheta > 8192)
+            /* Rough approximation for pre-echo masking */
+            delta -= delta>>(4-LM);
+         else
+            /* Corresponds to a forward-masking slope of 1.5 dB per 10 ms */
+            delta = IMIN(0, delta + (N<<BITRES>>(5-LM)));
+      }
+      mbits = IMAX(0, IMIN(b, (b-delta)/2));
+      sbits = b-mbits;
+      ctx->remaining_bits -= qalloc;
+
+      if (lowband)
+         next_lowband2 = lowband+N; /* >32-bit split case */
+
+      rebalance = ctx->remaining_bits;
+      if (mbits >= sbits)
+      {
+         cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
+               MULT32_32_Q31(gain,mid), fill ARG_QEXT(ext_b/2));
+         rebalance = mbits - (rebalance-ctx->remaining_bits);
+         if (rebalance > 3<<BITRES && itheta!=0)
+            sbits += rebalance - (3<<BITRES);
+         cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+               MULT32_32_Q31(gain,side), fill>>B ARG_QEXT(ext_b/2))<<(B0>>1);
+      } else {
+         cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+               MULT32_32_Q31(gain,side), fill>>B ARG_QEXT(ext_b/2))<<(B0>>1);
+         rebalance = sbits - (rebalance-ctx->remaining_bits);
+         if (rebalance > 3<<BITRES && itheta!=16384)
+            mbits += rebalance - (3<<BITRES);
+         cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
+               MULT32_32_Q31(gain,mid), fill ARG_QEXT(ext_b/2));
+      }
+   } else {
+#ifdef ENABLE_QEXT
+      int extra_bits;
+      int ext_remaining_bits;
+      extra_bits = ext_b/(N-1)>>BITRES;
+      ext_remaining_bits = ctx->ext_total_bits-(opus_int32)ec_tell_frac(ctx->ext_ec);
+      if (ext_remaining_bits < ((extra_bits+1)*(N-1)+N)<<BITRES) {
+         extra_bits = (ext_remaining_bits-(N<<BITRES))/(N-1)>>BITRES;
+         extra_bits = IMAX(extra_bits-1, 0);
+      }
+      extra_bits = IMIN(12, extra_bits);
+#endif
+      /* This is the basic no-split case */
+      q = bits2pulses(m, i, LM, b);
+      curr_bits = pulses2bits(m, i, LM, q);
+      ctx->remaining_bits -= curr_bits;
+
+      /* Ensures we can never bust the budget */
+      while (ctx->remaining_bits < 0 && q > 0)
+      {
+         ctx->remaining_bits += curr_bits;
+         q--;
+         curr_bits = pulses2bits(m, i, LM, q);
+         ctx->remaining_bits -= curr_bits;
+      }
+
+      if (q!=0)
+      {
+         int K = get_pulses(q);
+
+         /* Finally do the actual quantization */
+         if (encode)
+         {
+            cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth
+                           ARG_QEXT(ctx->ext_ec) ARG_QEXT(extra_bits),
+                           ctx->arch);
+         } else {
+            cm = alg_unquant(X, N, K, spread, B, ec, gain
+                             ARG_QEXT(ctx->ext_ec) ARG_QEXT(extra_bits));
+         }
+#ifdef ENABLE_QEXT
+      } else if (ext_b > 2*N<<BITRES)
+      {
+         extra_bits = ext_b/(N-1)>>BITRES;
+         ext_remaining_bits = ctx->ext_total_bits-ec_tell_frac(ctx->ext_ec);
+         if (ext_remaining_bits < ((extra_bits+1)*(N-1)+N)<<BITRES) {
+            extra_bits = (ext_remaining_bits-(N<<BITRES))/(N-1)>>BITRES;
+            extra_bits = IMAX(extra_bits-1, 0);
+         }
+         extra_bits = IMIN(14, extra_bits);
+         if (encode) cm = cubic_quant(X, N, extra_bits, B, ctx->ext_ec, gain, ctx->resynth);
+         else cm = cubic_unquant(X, N, extra_bits, B, ctx->ext_ec, gain);
+#endif
+      } else {
+         /* If there's no pulse, fill the band anyway */
+         int j;
+         if (ctx->resynth)
+         {
+            unsigned cm_mask;
+            /* B can be as large as 16, so this shift might overflow an int on a
+               16-bit platform; use a long to get defined behavior.*/
+            cm_mask = (unsigned)(1UL<<B)-1;
+            fill &= cm_mask;
+            if (!fill)
+            {
+               OPUS_CLEAR(X, N);
+            } else {
+               if (lowband == NULL)
+               {
+                  /* Noise */
+                  for (j=0;j<N;j++)
+                  {
+                     ctx->seed = celt_lcg_rand(ctx->seed);
+                     X[j] = SHL32((celt_norm)((opus_int32)ctx->seed>>20), NORM_SHIFT-14);
+                  }
+                  cm = cm_mask;
+               } else {
+                  /* Folded spectrum */
+                  for (j=0;j<N;j++)
+                  {
+                     opus_val16 tmp;
+                     ctx->seed = celt_lcg_rand(ctx->seed);
+                     /* About 48 dB below the "normal" folding level */
+                     tmp = QCONST16(1.0f/256, NORM_SHIFT-4);
+                     tmp = (ctx->seed)&0x8000 ? tmp : -tmp;
+                     X[j] = lowband[j]+tmp;
+                  }
+                  cm = fill;
+               }
+               renormalise_vector(X, N, gain, ctx->arch);
+            }
+         }
+      }
+   }
+
+   return cm;
+}
+
+#ifdef ENABLE_QEXT
+static unsigned cubic_quant_partition(struct band_ctx *ctx, celt_norm *X, int N, int b, int B, ec_ctx *ec, int LM, opus_val32 gain, int resynth, int encode)
+{
+   celt_assert(LM>=0);
+   ctx->remaining_bits = ctx->ec->storage*8*8 - ec_tell_frac(ctx->ec);
+   b = IMIN(b, ctx->remaining_bits);
+   /* As long as we have at least two bits of depth, split all the way to LM=0 (not -1 like PVQ). */
+   if (LM==0 || b<=2*N<<BITRES) {
+      int res, ret;
+      b = IMIN(b + ((N-1)<<BITRES)/2, ctx->remaining_bits);
+      /* Resolution left after taking into account coding the cube face. */
+      res = (b-(1<<BITRES)-ctx->m->logN[ctx->i]-(LM<<BITRES)-1)/(N-1)>>BITRES;
+      res = IMIN(14, IMAX(0, res));
+      if (encode) ret = cubic_quant(X, N, res, B, ec, gain, resynth);
+      else ret = cubic_unquant(X, N, res, B, ec, gain);
+      ctx->remaining_bits = ctx->ec->storage*8*8 - ec_tell_frac(ctx->ec);
+      return ret;
+   } else {
+      celt_norm *Y;
+      opus_int32 itheta_q30;
+      opus_val32 g1, g2;
+      opus_int32 theta_res;
+      opus_int32 qtheta;
+      int delta;
+      int b1, b2;
+      int cm;
+      int N0;
+      N0 = N;
+      N >>= 1;
+      Y = X+N;
+      LM -= 1;
+      B = (B+1)>>1;
+      theta_res = IMIN(16, (b>>BITRES)/(N0-1) + 1);
+      if (encode) {
+         itheta_q30 = stereo_itheta(X, Y, 0, N, ctx->arch);
+         qtheta = (itheta_q30+(1<<(29-theta_res)))>>(30-theta_res);
+         ec_enc_uint(ec, qtheta, (1<<theta_res)+1);
+      } else {
+         qtheta = ec_dec_uint(ec, (1<<theta_res)+1);
+      }
+      itheta_q30 = qtheta<<(30-theta_res);
+      b -= theta_res<<BITRES;
+      delta = (N0-1) * 23 * ((itheta_q30>>16)-8192) >> (17-BITRES);
+
+#ifdef FIXED_POINT
+      g1 = celt_cos_norm32(itheta_q30);
+      g2 = celt_cos_norm32((1<<30)-itheta_q30);
+#else
+      g1 = celt_cos_norm2(itheta_q30*(1.f/(1<<30)));
+      g2 = celt_cos_norm2(1.f-itheta_q30*(1.f/(1<<30)));
+#endif
+      if (itheta_q30 == 0) {
+         b1=b;
+         b2=0;
+      } else if (itheta_q30==1073741824) {
+         b1=0;
+         b2=b;
+      } else {
+         b1 = IMIN(b, IMAX(0, (b-delta)/2));
+         b2 = b-b1;
+      }
+      cm  = cubic_quant_partition(ctx, X, N, b1, B, ec, LM, MULT32_32_Q31(gain, g1), resynth, encode);
+      cm |= cubic_quant_partition(ctx, Y, N, b2, B, ec, LM, MULT32_32_Q31(gain, g2), resynth, encode);
+      return cm;
+   }
+}
+#endif
+
+/* This function is responsible for encoding and decoding a band for the mono case. */
+static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
+      int N, int b, int B, celt_norm *lowband,
+      int LM, celt_norm *lowband_out,
+      opus_val32 gain, celt_norm *lowband_scratch, int fill
+      ARG_QEXT(int ext_b))
+{
+   int N0=N;
+   int N_B=N;
+   int N_B0;
+   int B0=B;
+   int time_divide=0;
+   int recombine=0;
+   int longBlocks;
+   unsigned cm=0;
+   int k;
+   int encode;
+   int tf_change;
+
+   encode = ctx->encode;
+   tf_change = ctx->tf_change;
+
+   longBlocks = B0==1;
+
+   N_B = celt_udiv(N_B, B);
+
+   /* Special case for one sample */
+   if (N==1)
+   {
+      return quant_band_n1(ctx, X, NULL, lowband_out);
+   }
+
+   if (tf_change>0)
+      recombine = tf_change;
+   /* Band recombining to increase frequency resolution */
+
+   if (lowband_scratch && lowband && (recombine || ((N_B&1) == 0 && tf_change<0) || B0>1))
+   {
+      OPUS_COPY(lowband_scratch, lowband, N);
+      lowband = lowband_scratch;
+   }
+
+   for (k=0;k<recombine;k++)
+   {
+      static const unsigned char bit_interleave_table[16]={
+            0,1,1,1,2,3,3,3,2,3,3,3,2,3,3,3
+      };
+      if (encode)
+         haar1(X, N>>k, 1<<k);
+      if (lowband)
+         haar1(lowband, N>>k, 1<<k);
+      fill = bit_interleave_table[fill&0xF]|bit_interleave_table[fill>>4]<<2;
+   }
+   B>>=recombine;
+   N_B<<=recombine;
+
+   /* Increasing the time resolution */
+   while ((N_B&1) == 0 && tf_change<0)
+   {
+      if (encode)
+         haar1(X, N_B, B);
+      if (lowband)
+         haar1(lowband, N_B, B);
+      fill |= fill<<B;
+      B <<= 1;
+      N_B >>= 1;
+      time_divide++;
+      tf_change++;
+   }
+   B0=B;
+   N_B0 = N_B;
+
+   /* Reorganize the samples in time order instead of frequency order */
+   if (B0>1)
+   {
+      if (encode)
+         deinterleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
+      if (lowband)
+         deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
+   }
+
+#ifdef ENABLE_QEXT
+   if (ctx->extra_bands && b > (3*N<<BITRES)+(ctx->m->logN[ctx->i]+8+8*LM)) {
+      cm = cubic_quant_partition(ctx, X, N, b, B, ctx->ec, LM, gain, ctx->resynth, encode);
+   } else
+#endif
+   {
+      cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill ARG_QEXT(ext_b));
+   }
+
+   /* This code is used by the decoder and by the resynthesis-enabled encoder */
+   if (ctx->resynth)
+   {
+      /* Undo the sample reorganization going from time order to frequency order */
+      if (B0>1)
+         interleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
+
+      /* Undo time-freq changes that we did earlier */
+      N_B = N_B0;
+      B = B0;
+      for (k=0;k<time_divide;k++)
+      {
+         B >>= 1;
+         N_B <<= 1;
+         cm |= cm>>B;
+         haar1(X, N_B, B);
+      }
+
+      for (k=0;k<recombine;k++)
+      {
+         static const unsigned char bit_deinterleave_table[16]={
+               0x00,0x03,0x0C,0x0F,0x30,0x33,0x3C,0x3F,
+               0xC0,0xC3,0xCC,0xCF,0xF0,0xF3,0xFC,0xFF
+         };
+         cm = bit_deinterleave_table[cm];
+         haar1(X, N0>>k, 1<<k);
+      }
+      B<<=recombine;
+
+      /* Scale output for later folding */
+      if (lowband_out)
+      {
+         int j;
+         opus_val16 n;
+         n = celt_sqrt(SHL32(EXTEND32(N0),22));
+         for (j=0;j<N0;j++)
+            lowband_out[j] = MULT16_32_Q15(n,X[j]);
+      }
+      cm &= (1<<B)-1;
+   }
+   return cm;
+}
+
+#ifdef FIXED_POINT
+#define MIN_STEREO_ENERGY 2
+#else
+#define MIN_STEREO_ENERGY 1e-10f
+#endif
+
+/* This function is responsible for encoding and decoding a band for the stereo case. */
+static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
+      int N, int b, int B, celt_norm *lowband,
+      int LM, celt_norm *lowband_out,
+      celt_norm *lowband_scratch, int fill
+      ARG_QEXT(int ext_b) ARG_QEXT(const int *cap))
+{
+   int imid=0, iside=0;
+   int inv = 0;
+   opus_val32 mid=0, side=0;
+   unsigned cm=0;
+   int mbits, sbits, delta;
+   int itheta;
+   int qalloc;
+   struct split_ctx sctx;
+   int orig_fill;
+   int encode;
+   ec_ctx *ec;
+
+   encode = ctx->encode;
+   ec = ctx->ec;
+
+   /* Special case for one sample */
+   if (N==1)
+   {
+      return quant_band_n1(ctx, X, Y, lowband_out);
+   }
+
+   orig_fill = fill;
+
+   if (encode) {
+      if (ctx->bandE[ctx->i] < MIN_STEREO_ENERGY || ctx->bandE[ctx->m->nbEBands+ctx->i] < MIN_STEREO_ENERGY) {
+         if (ctx->bandE[ctx->i] > ctx->bandE[ctx->m->nbEBands+ctx->i]) OPUS_COPY(Y, X, N);
+         else OPUS_COPY(X, Y, N);
+      }
+   }
+   compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill ARG_QEXT(&ext_b));
+   inv = sctx.inv;
+   imid = sctx.imid;
+   iside = sctx.iside;
+   delta = sctx.delta;
+   itheta = sctx.itheta;
+   qalloc = sctx.qalloc;
+#ifdef FIXED_POINT
+# ifdef ENABLE_QEXT
+   (void)imid;
+   (void)iside;
+   mid = celt_cos_norm32(sctx.itheta_q30);
+   side = celt_cos_norm32((1<<30)-sctx.itheta_q30);
+# else
+   mid = SHL32(EXTEND32(imid), 16);
+   side = SHL32(EXTEND32(iside), 16);
+# endif
+#else
+# ifdef ENABLE_QEXT
+   (void)imid;
+   (void)iside;
+   mid = celt_cos_norm2(sctx.itheta_q30*(1.f/(1<<30)));
+   side = celt_cos_norm2(1.f-sctx.itheta_q30*(1.f/(1<<30)));
+# else
+   mid = (1.f/32768)*imid;
+   side = (1.f/32768)*iside;
+# endif
+#endif
+
+   /* This is a special case for N=2 that only works for stereo and takes
+      advantage of the fact that mid and side are orthogonal to encode
+      the side with just one bit. */
+   if (N==2)
+   {
+      int c;
+      int sign=0;
+      celt_norm *x2, *y2;
+      mbits = b;
+      sbits = 0;
+      /* Only need one bit for the side. */
+      if (itheta != 0 && itheta != 16384)
+         sbits = 1<<BITRES;
+      mbits -= sbits;
+      c = itheta > 8192;
+      ctx->remaining_bits -= qalloc+sbits;
+
+      x2 = c ? Y : X;
+      y2 = c ? X : Y;
+      if (sbits)
+      {
+         if (encode)
+         {
+            /* Here we only need to encode a sign for the side. */
+            /* FIXME: Need to increase fixed-point precision? */
+            sign = MULT32_32_Q31(x2[0],y2[1]) - MULT32_32_Q31(x2[1],y2[0]) < 0;
+            ec_enc_bits(ec, sign, 1);
+         } else {
+            sign = ec_dec_bits(ec, 1);
+         }
+      }
+      sign = 1-2*sign;
+      /* We use orig_fill here because we want to fold the side, but if
+         itheta==16384, we'll have cleared the low bits of fill. */
+      cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+            lowband_scratch, orig_fill ARG_QEXT(ext_b));
+      /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
+         and there's no need to worry about mixing with the other channel. */
+      y2[0] = -sign*x2[1];
+      y2[1] = sign*x2[0];
+      if (ctx->resynth)
+      {
+         celt_norm tmp;
+         X[0] = MULT32_32_Q31(mid, X[0]);
+         X[1] = MULT32_32_Q31(mid, X[1]);
+         Y[0] = MULT32_32_Q31(side, Y[0]);
+         Y[1] = MULT32_32_Q31(side, Y[1]);
+         tmp = X[0];
+         X[0] = SUB32(tmp,Y[0]);
+         Y[0] = ADD32(tmp,Y[0]);
+         tmp = X[1];
+         X[1] = SUB32(tmp,Y[1]);
+         Y[1] = ADD32(tmp,Y[1]);
+      }
+   } else {
+      /* "Normal" split code */
+      opus_int32 rebalance;
+
+      mbits = IMAX(0, IMIN(b, (b-delta)/2));
+      sbits = b-mbits;
+      ctx->remaining_bits -= qalloc;
+
+      rebalance = ctx->remaining_bits;
+      if (mbits >= sbits)
+      {
+#ifdef ENABLE_QEXT
+         int qext_extra = 0;
+         /* Reallocate any mid bits that cannot be used to extra mid bits. */
+         if (cap != NULL && ext_b != 0) qext_extra = IMAX(0, IMIN(ext_b/2, mbits - cap[ctx->i]/2));
+#endif
+         /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
+            mid for folding later. */
+         cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+               lowband_scratch, fill ARG_QEXT(ext_b/2+qext_extra));
+         rebalance = mbits - (rebalance-ctx->remaining_bits);
+         if (rebalance > 3<<BITRES && itheta!=0)
+            sbits += rebalance - (3<<BITRES);
+#ifdef ENABLE_QEXT
+         /* Guard against overflowing the EC with the angle if the cubic quant used too many bits for the mid. */
+         if (ctx->extra_bands) sbits = IMIN(sbits, ctx->remaining_bits);
+#endif
+         /* For a stereo split, the high bits of fill are always zero, so no
+            folding will be done to the side. */
+         cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B ARG_QEXT(ext_b/2-qext_extra));
+      } else {
+#ifdef ENABLE_QEXT
+         int qext_extra = 0;
+         /* Reallocate any side bits that cannot be used to extra side bits. */
+         if (cap != NULL && ext_b != 0) qext_extra = IMAX(0, IMIN(ext_b/2, sbits - cap[ctx->i]/2));
+#endif
+         /* For a stereo split, the high bits of fill are always zero, so no
+            folding will be done to the side. */
+         cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B ARG_QEXT(ext_b/2+qext_extra));
+         rebalance = sbits - (rebalance-ctx->remaining_bits);
+         if (rebalance > 3<<BITRES && itheta!=16384)
+            mbits += rebalance - (3<<BITRES);
+#ifdef ENABLE_QEXT
+         /* Guard against overflowing the EC with the angle if the cubic quant used too many bits for the side. */
+         if (ctx->extra_bands) mbits = IMIN(mbits, ctx->remaining_bits);
+#endif
+         /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
+            mid for folding later. */
+         cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+               lowband_scratch, fill ARG_QEXT(ext_b/2-qext_extra));
+      }
+   }
+
+
+   /* This code is used by the decoder and by the resynthesis-enabled encoder */
+   if (ctx->resynth)
+   {
+      if (N!=2)
+         stereo_merge(X, Y, mid, N, ctx->arch);
+      if (inv)
+      {
+         int j;
+         for (j=0;j<N;j++)
+            Y[j] = -Y[j];
+      }
+   }
+   return cm;
+}
+
+#ifndef DISABLE_UPDATE_DRAFT
+static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
+{
+   int n1, n2;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   n1 = M*(eBands[start+1]-eBands[start]);
+   n2 = M*(eBands[start+2]-eBands[start+1]);
+   /* Duplicate enough of the first band folding data to be able to fold the second band.
+      Copies no data for CELT-only mode. */
+   OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
+   if (dual_stereo)
+      OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
+}
+#endif
+
+void quant_all_bands(int encode, const CELTMode *m, int start, int end,
+      celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
+      const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
+      int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
+      opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
+      opus_uint32 *seed, int complexity, int arch, int disable_inv
+      ARG_QEXT(ec_ctx *ext_ec) ARG_QEXT(int *extra_pulses)
+      ARG_QEXT(opus_int32 ext_total_bits) ARG_QEXT(const int *cap))
+{
+   int i;
+   opus_int32 remaining_bits;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
+   VARDECL(celt_norm, _norm);
+   VARDECL(celt_norm, _lowband_scratch);
+   VARDECL(celt_norm, X_save);
+   VARDECL(celt_norm, Y_save);
+   VARDECL(celt_norm, X_save2);
+   VARDECL(celt_norm, Y_save2);
+   VARDECL(celt_norm, norm_save2);
+   VARDECL(unsigned char, bytes_save);
+   int resynth_alloc;
+   celt_norm *lowband_scratch;
+   int B;
+   int M;
+   int lowband_offset;
+   int update_lowband = 1;
+   int C = Y_ != NULL ? 2 : 1;
+   int norm_offset;
+   int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
+#ifdef RESYNTH
+   int resynth = 1;
+#else
+   int resynth = !encode || theta_rdo;
+#endif
+   struct band_ctx ctx;
+#ifdef ENABLE_QEXT
+   int ext_b;
+   opus_int32 ext_balance=0;
+   opus_int32 ext_tell=0;
+   VARDECL(unsigned char, ext_bytes_save);
+#endif
+   SAVE_STACK;
+
+   M = 1<<LM;
+   B = shortBlocks ? M : 1;
+   norm_offset = M*eBands[start];
+   /* No need to allocate norm for the last band because we don't need an
+      output in that band. */
+   ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
+   norm = _norm;
+   norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
+
+   /* For decoding, we can use the last band as scratch space because we don't need that
+      scratch space for the last band and we don't care about the data there until we're
+      decoding the last band. */
+   if (encode && resynth)
+      resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
+   else
+      resynth_alloc = ALLOC_NONE;
+   ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
+   if (encode && resynth)
+      lowband_scratch = _lowband_scratch;
+   else
+      lowband_scratch = X_+M*eBands[m->effEBands-1];
+   ALLOC(X_save, resynth_alloc, celt_norm);
+   ALLOC(Y_save, resynth_alloc, celt_norm);
+   ALLOC(X_save2, resynth_alloc, celt_norm);
+   ALLOC(Y_save2, resynth_alloc, celt_norm);
+   ALLOC(norm_save2, resynth_alloc, celt_norm);
+
+   lowband_offset = 0;
+   ctx.bandE = bandE;
+   ctx.ec = ec;
+   ctx.encode = encode;
+   ctx.intensity = intensity;
+   ctx.m = m;
+   ctx.seed = *seed;
+   ctx.spread = spread;
+   ctx.arch = arch;
+   ctx.disable_inv = disable_inv;
+   ctx.resynth = resynth;
+   ctx.theta_round = 0;
+#ifdef ENABLE_QEXT
+   ctx.ext_ec = ext_ec;
+   ctx.ext_total_bits = ext_total_bits;
+   ctx.extra_bands = end == NB_QEXT_BANDS || end == 2;
+   if (ctx.extra_bands) theta_rdo = 0;
+   ALLOC(ext_bytes_save, theta_rdo ? QEXT_PACKET_SIZE_CAP : ALLOC_NONE, unsigned char);
+#endif
+   ALLOC(bytes_save, theta_rdo ? 1275 : ALLOC_NONE, unsigned char);
+
+   /* Avoid injecting noise in the first band on transients. */
+   ctx.avoid_split_noise = B > 1;
+   for (i=start;i<end;i++)
+   {
+      opus_int32 tell;
+      int b;
+      int N;
+      opus_int32 curr_balance;
+      int effective_lowband=-1;
+      celt_norm * OPUS_RESTRICT X, * OPUS_RESTRICT Y;
+      int tf_change=0;
+      unsigned x_cm;
+      unsigned y_cm;
+      int last;
+
+      ctx.i = i;
+      last = (i==end-1);
+
+      X = X_+M*eBands[i];
+      if (Y_!=NULL)
+         Y = Y_+M*eBands[i];
+      else
+         Y = NULL;
+      N = M*eBands[i+1]-M*eBands[i];
+      celt_assert(N > 0);
+      tell = ec_tell_frac(ec);
+
+      /* Compute how many bits we want to allocate to this band */
+      if (i != start)
+         balance -= tell;
+      remaining_bits = total_bits-tell-1;
+      ctx.remaining_bits = remaining_bits;
+#ifdef ENABLE_QEXT
+      if (i != start) {
+         ext_balance += extra_pulses[i-1] + ext_tell;
+      }
+      ext_tell = ec_tell_frac(ext_ec);
+      ctx.extra_bits = extra_pulses[i];
+      if (i != start)
+         ext_balance -= ext_tell;
+      if (i <= codedBands-1)
+      {
+         opus_int32 ext_curr_balance = celt_sudiv(ext_balance, IMIN(3, codedBands-i));
+         ext_b = IMAX(0, IMIN(16383, IMIN(ext_total_bits-ext_tell,extra_pulses[i]+ext_curr_balance)));
+      } else {
+         ext_b = 0;
+      }
+#endif
+      if (i <= codedBands-1)
+      {
+         curr_balance = celt_sudiv(balance, IMIN(3, codedBands-i));
+         b = IMAX(0, IMIN(16383, IMIN(remaining_bits+1,pulses[i]+curr_balance)));
+      } else {
+         b = 0;
+      }
+
+#ifndef DISABLE_UPDATE_DRAFT
+      if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
+            lowband_offset = i;
+      if (i == start+1)
+         special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#else
+      if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
+            lowband_offset = i;
+#endif
+
+      tf_change = tf_res[i];
+      ctx.tf_change = tf_change;
+      if (i>=m->effEBands)
+      {
+         X=norm;
+         if (Y_!=NULL)
+            Y = norm;
+         lowband_scratch = NULL;
+      }
+      if (last && !theta_rdo)
+         lowband_scratch = NULL;
+
+      /* Get a conservative estimate of the collapse_mask's for the bands we're
+         going to be folding from. */
+      if (lowband_offset != 0 && (spread!=SPREAD_AGGRESSIVE || B>1 || tf_change<0))
+      {
+         int fold_start;
+         int fold_end;
+         int fold_i;
+         /* This ensures we never repeat spectral content within one band */
+         effective_lowband = IMAX(0, M*eBands[lowband_offset]-norm_offset-N);
+         fold_start = lowband_offset;
+         while(M*eBands[--fold_start] > effective_lowband+norm_offset);
+         fold_end = lowband_offset-1;
+#ifndef DISABLE_UPDATE_DRAFT
+         while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
+#else
+         while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
+#endif
+         x_cm = y_cm = 0;
+         fold_i = fold_start; do {
+           x_cm |= collapse_masks[fold_i*C+0];
+           y_cm |= collapse_masks[fold_i*C+C-1];
+         } while (++fold_i<fold_end);
+      }
+      /* Otherwise, we'll be using the LCG to fold, so all blocks will (almost
+         always) be non-zero. */
+      else
+         x_cm = y_cm = (1<<B)-1;
+
+      if (dual_stereo && i==intensity)
+      {
+         int j;
+
+         /* Switch off dual stereo to do intensity. */
+         dual_stereo = 0;
+         if (resynth)
+            for (j=0;j<M*eBands[i]-norm_offset;j++)
+               norm[j] = HALF32(norm[j]+norm2[j]);
+      }
+      if (dual_stereo)
+      {
+         x_cm = quant_band(&ctx, X, N, b/2, B,
+               effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+               last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm ARG_QEXT(ext_b/2));
+         y_cm = quant_band(&ctx, Y, N, b/2, B,
+               effective_lowband != -1 ? norm2+effective_lowband : NULL, LM,
+               last?NULL:norm2+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, y_cm ARG_QEXT(ext_b/2));
+      } else {
+         if (Y!=NULL)
+         {
+            if (theta_rdo && i < intensity)
+            {
+               ec_ctx ec_save, ec_save2;
+               struct band_ctx ctx_save, ctx_save2;
+               opus_val32 dist0, dist1;
+               unsigned cm, cm2;
+               int nstart_bytes, nend_bytes, save_bytes;
+               unsigned char *bytes_buf;
+#ifdef ENABLE_QEXT
+               ec_ctx ext_ec_save, ext_ec_save2;
+               unsigned char *ext_bytes_buf;
+               int ext_nstart_bytes, ext_nend_bytes, ext_save_bytes;
+#endif
+               opus_val16 w[2];
+               compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
+               /* Make a copy. */
+               cm = x_cm|y_cm;
+               ec_save = *ec;
+#ifdef ENABLE_QEXT
+               ext_ec_save = *ext_ec;
+#endif
+               ctx_save = ctx;
+               OPUS_COPY(X_save, X, N);
+               OPUS_COPY(Y_save, Y, N);
+               /* Encode and round down. */
+               ctx.theta_round = -1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+               dist0 = MULT16_32_Q15(w[0], celt_inner_prod_norm_shift(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod_norm_shift(Y_save, Y, N, arch));
+
+               /* Save first result. */
+               cm2 = x_cm;
+               ec_save2 = *ec;
+#ifdef ENABLE_QEXT
+               ext_ec_save2 = *ext_ec;
+#endif
+               ctx_save2 = ctx;
+               OPUS_COPY(X_save2, X, N);
+               OPUS_COPY(Y_save2, Y, N);
+               if (!last)
+                  OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
+               nstart_bytes = ec_save.offs;
+               nend_bytes = ec_save.storage;
+               bytes_buf = ec_save.buf+nstart_bytes;
+               save_bytes = nend_bytes-nstart_bytes;
+               OPUS_COPY(bytes_save, bytes_buf, save_bytes);
+#ifdef ENABLE_QEXT
+               ext_nstart_bytes = ext_ec_save.offs;
+               ext_nend_bytes = ext_ec_save.storage;
+               ext_bytes_buf = ext_ec_save.buf!=NULL ? ext_ec_save.buf+ext_nstart_bytes : NULL;
+               ext_save_bytes = ext_nend_bytes-ext_nstart_bytes;
+               if (ext_save_bytes) OPUS_COPY(ext_bytes_save, ext_bytes_buf, ext_save_bytes);
+#endif
+               /* Restore */
+               *ec = ec_save;
+#ifdef ENABLE_QEXT
+               *ext_ec = ext_ec_save;
+#endif
+               ctx = ctx_save;
+               OPUS_COPY(X, X_save, N);
+               OPUS_COPY(Y, Y_save, N);
+#ifndef DISABLE_UPDATE_DRAFT
+               if (i == start+1)
+                  special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#endif
+               /* Encode and round up. */
+               ctx.theta_round = 1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+               dist1 = MULT16_32_Q15(w[0], celt_inner_prod_norm_shift(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod_norm_shift(Y_save, Y, N, arch));
+               if (dist0 >= dist1) {
+                  x_cm = cm2;
+                  *ec = ec_save2;
+#ifdef ENABLE_QEXT
+                  *ext_ec = ext_ec_save2;
+#endif
+                  ctx = ctx_save2;
+                  OPUS_COPY(X, X_save2, N);
+                  OPUS_COPY(Y, Y_save2, N);
+                  if (!last)
+                     OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
+                  OPUS_COPY(bytes_buf, bytes_save, save_bytes);
+#ifdef ENABLE_QEXT
+                  if (ext_save_bytes) OPUS_COPY(ext_bytes_buf, ext_bytes_save, ext_save_bytes);
+#endif
+               }
+            } else {
+               ctx.theta_round = 0;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+            }
+         } else {
+            x_cm = quant_band(&ctx, X, N, b, B,
+                  effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                  last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm|y_cm ARG_QEXT(ext_b));
+         }
+         y_cm = x_cm;
+      }
+      collapse_masks[i*C+0] = (unsigned char)x_cm;
+      collapse_masks[i*C+C-1] = (unsigned char)y_cm;
+      balance += pulses[i] + tell;
+
+      /* Update the folding position only as long as we have 1 bit/sample depth. */
+      update_lowband = b>(N<<BITRES);
+      /* We only need to avoid noise on a split for the first band. After that, we
+         have folding. */
+      ctx.avoid_split_noise = 0;
+   }
+   *seed = ctx.seed;
+
+   RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/bands.h
new file mode 100644 (file)
index 0000000..e7fee53
--- /dev/null
@@ -0,0 +1,125 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008-2009 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef BANDS_H
+#define BANDS_H
+
+#include "arch.h"
+#include "modes.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "rate.h"
+
+opus_int16 bitexact_cos(opus_int16 x);
+int bitexact_log2tan(int isin,int icos);
+
+/** Compute the amplitude (sqrt energy) in each of the bands
+ * @param m Mode data
+ * @param X Spectrum
+ * @param bandE Square root of the energy for each band (returned)
+ */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
+
+/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
+
+/** Normalise each band of X such that the energy in each band is
+    equal to 1
+ * @param m Mode data
+ * @param X Spectrum (returned normalised)
+ * @param bandE Square root of the energy for each band
+ */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
+
+/** Denormalise each band of X to restore full amplitude
+ * @param m Mode data
+ * @param X Spectrum (returned de-normalised)
+ * @param bandE Square root of the energy for each band
+ */
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
+      celt_sig * OPUS_RESTRICT freq, const celt_glog *bandE, int start,
+      int end, int M, int downsample, int silence);
+
+#define SPREAD_NONE       (0)
+#define SPREAD_LIGHT      (1)
+#define SPREAD_NORMAL     (2)
+#define SPREAD_AGGRESSIVE (3)
+
+int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
+      int last_decision, int *hf_average, int *tapset_decision, int update_hf,
+      int end, int C, int M, const int *spread_weight);
+
+#ifdef MEASURE_NORM_MSE
+void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
+#endif
+
+void haar1(celt_norm *X, int N0, int stride);
+
+/** Quantisation/encoding of the residual spectrum
+ * @param encode flag that indicates whether we're encoding (1) or decoding (0)
+ * @param m Mode data
+ * @param start First band to process
+ * @param end Last band to process + 1
+ * @param X Residual (normalised)
+ * @param Y Residual (normalised) for second channel (or NULL for mono)
+ * @param collapse_masks Anti-collapse tracking mask
+ * @param bandE Square root of the energy for each band
+ * @param pulses Bit allocation (per band) for PVQ
+ * @param shortBlocks Zero for long blocks, non-zero for short blocks
+ * @param spread Amount of spreading to use
+ * @param dual_stereo Zero for MS stereo, non-zero for dual stereo
+ * @param intensity First band to use intensity stereo
+ * @param tf_res Time-frequency resolution change
+ * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
+ * @param balance Number of unallocated bits
+ * @param en Entropy coder state
+ * @param LM log2() of the number of 2.5 subframes in the frame
+ * @param codedBands Last band to receive bits + 1
+ * @param seed Random generator seed
+ * @param arch Run-time architecture (see opus_select_arch())
+ */
+void quant_all_bands(int encode, const CELTMode *m, int start, int end,
+      celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
+      const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
+      int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
+      opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
+      int complexity, int arch, int disable_inv
+      ARG_QEXT(ec_ctx *ext_ec) ARG_QEXT(int *extra_pulses)
+      ARG_QEXT(opus_int32 total_ext_bits) ARG_QEXT(const int *cap));
+
+void anti_collapse(const CELTMode *m, celt_norm *X_,
+      unsigned char *collapse_masks, int LM, int C, int size, int start,
+      int end, const celt_glog *logE, const celt_glog *prev1logE,
+      const celt_glog *prev2logE, const int *pulses, opus_uint32 seed,
+      int encode, int arch);
+
+opus_uint32 celt_lcg_rand(opus_uint32 seed);
+
+int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev);
+
+#endif /* BANDS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.c
new file mode 100644 (file)
index 0000000..c0db737
--- /dev/null
@@ -0,0 +1,373 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2010 Xiph.Org Foundation
+   Copyright (c) 2008 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CELT_C
+
+#include "os_support.h"
+#include "mdct.h"
+#include <math.h>
+#include "celt.h"
+#include "pitch.h"
+#include "bands.h"
+#include "modes.h"
+#include "entcode.h"
+#include "quant_bands.h"
+#include "rate.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "float_cast.h"
+#include <stdarg.h>
+#include "celt_lpc.h"
+#include "vq.h"
+
+#ifndef PACKAGE_VERSION
+#define PACKAGE_VERSION "unknown"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/celt_mipsr1.h"
+#endif
+
+
+int resampling_factor(opus_int32 rate)
+{
+   int ret;
+   switch (rate)
+   {
+#ifdef ENABLE_QEXT
+   case 96000:
+#endif
+   case 48000:
+      ret = 1;
+      break;
+   case 24000:
+      ret = 2;
+      break;
+   case 16000:
+      ret = 3;
+      break;
+   case 12000:
+      ret = 4;
+      break;
+   case 8000:
+      ret = 6;
+      break;
+   default:
+#ifndef CUSTOM_MODES
+      celt_assert(0);
+#endif
+      ret = 0;
+      break;
+   }
+   return ret;
+}
+
+
+#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
+/* This version should be faster on ARM */
+#ifdef OPUS_ARM_ASM
+#ifndef NON_STATIC_COMB_FILTER_CONST_C
+static
+#endif
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+      celt_coef g10, celt_coef g11, celt_coef g12)
+{
+   opus_val32 x0, x1, x2, x3, x4;
+   int i;
+   x4 = SHL32(x[-T-2], 1);
+   x3 = SHL32(x[-T-1], 1);
+   x2 = SHL32(x[-T], 1);
+   x1 = SHL32(x[-T+1], 1);
+   for (i=0;i<N-4;i+=5)
+   {
+      opus_val32 t;
+      x0=SHL32(x[i-T+2],1);
+      t = MAC_COEF_32_ARM(x[i], g10, x2);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
+      y[i] = t;
+      x4=SHL32(x[i-T+3],1);
+      t = MAC_COEF_32_ARM(x[i+1], g10, x1);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x0,x2));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x4,x3));
+      t = SATURATE(t, SIG_SAT);
+      y[i+1] = t;
+      x3=SHL32(x[i-T+4],1);
+      t = MAC_COEF_32_ARM(x[i+2], g10, x0);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x4,x1));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x3,x2));
+      t = SATURATE(t, SIG_SAT);
+      y[i+2] = t;
+      x2=SHL32(x[i-T+5],1);
+      t = MAC_COEF_32_ARM(x[i+3], g10, x4);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x3,x0));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x2,x1));
+      t = SATURATE(t, SIG_SAT);
+      y[i+3] = t;
+      x1=SHL32(x[i-T+6],1);
+      t = MAC_COEF_32_ARM(x[i+4], g10, x3);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x2,x4));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x1,x0));
+      t = SATURATE(t, SIG_SAT);
+      y[i+4] = t;
+   }
+#ifdef CUSTOM_MODES
+   for (;i<N;i++)
+   {
+      opus_val32 t;
+      x0=SHL32(x[i-T+2],1);
+      t = MAC_COEF_32_ARM(x[i], g10, x2);
+      t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
+      t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
+      y[i] = t;
+      x4=x3;
+      x3=x2;
+      x2=x1;
+      x1=x0;
+   }
+#endif
+}
+#else
+#ifndef NON_STATIC_COMB_FILTER_CONST_C
+static
+#endif
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+      celt_coef g10, celt_coef g11, celt_coef g12)
+{
+   opus_val32 x0, x1, x2, x3, x4;
+   int i;
+   x4 = x[-T-2];
+   x3 = x[-T-1];
+   x2 = x[-T];
+   x1 = x[-T+1];
+   for (i=0;i<N;i++)
+   {
+      x0=x[i-T+2];
+      y[i] = x[i]
+               + MULT_COEF_32(g10,x2)
+               + MULT_COEF_32(g11,ADD32(x1,x3))
+               + MULT_COEF_32(g12,ADD32(x0,x4));
+#ifdef FIXED_POINT
+      /* A bit of bias seems to help here. */
+      y[i] = SUB32(y[i], 1);
+#endif
+      y[i] = SATURATE(y[i], SIG_SAT);
+      x4=x3;
+      x3=x2;
+      x2=x1;
+      x1=x0;
+   }
+
+}
+#endif
+#endif
+
+#ifdef ENABLE_QEXT
+void comb_filter_qext(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+      opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+      const celt_coef *window, int overlap, int arch)
+{
+   VARDECL(opus_val32, mem_buf);
+   VARDECL(opus_val32, buf);
+   celt_coef new_window[120];
+   int s;
+   int i;
+   int N2;
+   int overlap2;
+   SAVE_STACK;
+   /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+      This is useful on some embedded systems. */
+   ALLOC(mem_buf, COMBFILTER_MAXPERIOD+960, opus_val32);
+   ALLOC(buf, COMBFILTER_MAXPERIOD+960, opus_val32);
+   N2 = N/2;
+   overlap2=overlap/2;
+   /* At 96 kHz, we double the period and the spacing between taps, which is equivalent
+      to creating a mirror image of the filter around 24 kHz. It also means we can process
+      the even and odd samples completely independently. */
+   for (s=0;s<2;s++) {
+      opus_val32 *yptr;
+      for (i=0;i<overlap2;i++) new_window[i] = window[2*i+s];
+      for (i=0;i<COMBFILTER_MAXPERIOD+N2;i++) mem_buf[i] = x[2*i+s-2*COMBFILTER_MAXPERIOD];
+      if (x==y) {
+         yptr = mem_buf+COMBFILTER_MAXPERIOD;
+      } else {
+         for (i=0;i<N2;i++) buf[i] = y[2*i+s];
+         yptr = buf;
+      }
+      comb_filter(yptr, mem_buf+COMBFILTER_MAXPERIOD, T0, T1, N2, g0, g1, tapset0, tapset1, new_window, overlap2, arch);
+      for (i=0;i<N2;i++) y[2*i+s] = yptr[i];
+   }
+   RESTORE_STACK;
+   return;
+}
+#endif
+
+#ifndef OVERRIDE_comb_filter
+void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+      opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+      const celt_coef *window, int overlap, int arch)
+{
+   int i;
+   /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
+   celt_coef g00, g01, g02, g10, g11, g12;
+   opus_val32 x0, x1, x2, x3, x4;
+   static const opus_val16 gains[3][3] = {
+         {QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
+         {QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
+         {QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
+#ifdef ENABLE_QEXT
+   if (overlap==240) {
+      comb_filter_qext(y, x, T0, T1, N, g0, g1, tapset0, tapset1, window, overlap, arch);
+      return;
+   }
+#endif
+   if (g0==0 && g1==0)
+   {
+      /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
+      if (x!=y)
+         OPUS_MOVE(y, x, N);
+      return;
+   }
+   /* When the gain is zero, T0 and/or T1 is set to zero. We need
+      to have then be at least 2 to avoid processing garbage data. */
+   T0 = IMAX(T0, COMBFILTER_MINPERIOD);
+   T1 = IMAX(T1, COMBFILTER_MINPERIOD);
+   g00 = MULT_COEF_TAPS(g0, gains[tapset0][0]);
+   g01 = MULT_COEF_TAPS(g0, gains[tapset0][1]);
+   g02 = MULT_COEF_TAPS(g0, gains[tapset0][2]);
+   g10 = MULT_COEF_TAPS(g1, gains[tapset1][0]);
+   g11 = MULT_COEF_TAPS(g1, gains[tapset1][1]);
+   g12 = MULT_COEF_TAPS(g1, gains[tapset1][2]);
+   x1 = x[-T1+1];
+   x2 = x[-T1  ];
+   x3 = x[-T1-1];
+   x4 = x[-T1-2];
+   /* If the filter didn't change, we don't need the overlap */
+   if (g0==g1 && T0==T1 && tapset0==tapset1)
+      overlap=0;
+   for (i=0;i<overlap;i++)
+   {
+      celt_coef f;
+      x0=x[i-T1+2];
+      f = MULT_COEF(window[i],window[i]);
+      y[i] = x[i]
+               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g00),x[i-T0])
+               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
+               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
+               + MULT_COEF_32(MULT_COEF(f,g10),x2)
+               + MULT_COEF_32(MULT_COEF(f,g11),ADD32(x1,x3))
+               + MULT_COEF_32(MULT_COEF(f,g12),ADD32(x0,x4));
+#ifdef FIXED_POINT
+      /* A bit of bias seems to help here. */
+      y[i] = SUB32(y[i], 3);
+#endif
+      y[i] = SATURATE(y[i], SIG_SAT);
+      x4=x3;
+      x3=x2;
+      x2=x1;
+      x1=x0;
+
+   }
+   if (g1==0)
+   {
+      /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
+      if (x!=y)
+         OPUS_MOVE(y+overlap, x+overlap, N-overlap);
+      return;
+   }
+
+   /* Compute the part with the constant filter. */
+   comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
+}
+#endif /* OVERRIDE_comb_filter */
+
+/* TF change table. Positive values mean better frequency resolution (longer
+   effective window), whereas negative values mean better time resolution
+   (shorter effective window). The second index is computed as:
+   4*isTransient + 2*tf_select + per_band_flag */
+const signed char tf_select_table[4][8] = {
+    /*isTransient=0     isTransient=1 */
+      {0, -1, 0, -1,    0,-1, 0,-1}, /* 2.5 ms */
+      {0, -1, 0, -2,    1, 0, 1,-1}, /* 5 ms */
+      {0, -2, 0, -3,    2, 0, 1,-1}, /* 10 ms */
+      {0, -2, 0, -3,    3, 0, 1,-1}, /* 20 ms */
+};
+
+
+void init_caps(const CELTMode *m,int *cap,int LM,int C)
+{
+   int i;
+   for (i=0;i<m->nbEBands;i++)
+   {
+      int N;
+      N=(m->eBands[i+1]-m->eBands[i])<<LM;
+      cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
+   }
+}
+
+
+
+const char *opus_strerror(int error)
+{
+   static const char * const error_strings[8] = {
+      "success",
+      "invalid argument",
+      "buffer too small",
+      "internal error",
+      "corrupted stream",
+      "request not implemented",
+      "invalid state",
+      "memory allocation failed"
+   };
+   if (error > 0 || error < -7)
+      return "unknown error";
+   else
+      return error_strings[-error];
+}
+
+const char *opus_get_version_string(void)
+{
+    return "libopus " PACKAGE_VERSION
+    /* Applications may rely on the presence of this substring in the version
+       string to determine if they have a fixed-point or floating-point build
+       at runtime. */
+#ifdef FIXED_POINT
+          "-fixed"
+#endif
+#ifdef FUZZING
+          "-fuzzing"
+#endif
+          ;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt.h
new file mode 100644 (file)
index 0000000..c33e11e
--- /dev/null
@@ -0,0 +1,274 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/**
+  @file celt.h
+  @brief Contains all the functions for encoding and decoding audio
+ */
+
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CELT_H
+#define CELT_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "opus_custom.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "arch.h"
+#include "kiss_fft.h"
+
+#ifdef ENABLE_QEXT
+#define ARG_QEXT(arg) , arg
+#else
+#define ARG_QEXT(arg)
+#endif
+
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#endif
+
+#define CELTEncoder OpusCustomEncoder
+#define CELTDecoder OpusCustomDecoder
+#define CELTMode OpusCustomMode
+
+#define QEXT_EXTENSION_ID 124
+
+#define LEAK_BANDS 19
+
+typedef struct {
+   int valid;
+   float tonality;
+   float tonality_slope;
+   float noisiness;
+   float activity;
+   float music_prob;
+   float music_prob_min;
+   float music_prob_max;
+   int   bandwidth;
+   float activity_probability;
+   float max_pitch_ratio;
+   /* Store as Q6 char to save space. */
+   unsigned char leak_boost[LEAK_BANDS];
+} AnalysisInfo;
+
+typedef struct {
+   int signalType;
+   int offset;
+} SILKInfo;
+
+#define celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
+
+#define celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
+
+#define celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
+
+#define celt_check_glog_ptr(ptr) ((ptr) + ((ptr) - (celt_glog*)(ptr)))
+
+/* Encoder/decoder Requests */
+
+
+#define CELT_SET_PREDICTION_REQUEST    10002
+/** Controls the use of interframe prediction.
+    0=Independent frames
+    1=Short term interframe prediction allowed
+    2=Long term prediction allowed
+ */
+#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, opus_check_int(x)
+
+#define CELT_SET_INPUT_CLIPPING_REQUEST    10004
+#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, opus_check_int(x)
+
+#define CELT_GET_AND_CLEAR_ERROR_REQUEST   10007
+#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, opus_check_int_ptr(x)
+
+#define CELT_SET_CHANNELS_REQUEST    10008
+#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, opus_check_int(x)
+
+
+/* Internal */
+#define CELT_SET_START_BAND_REQUEST    10010
+#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, opus_check_int(x)
+
+#define CELT_SET_END_BAND_REQUEST    10012
+#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, opus_check_int(x)
+
+#define CELT_GET_MODE_REQUEST    10015
+/** Get the CELTMode used by an encoder or decoder */
+#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, celt_check_mode_ptr_ptr(x)
+
+#define CELT_SET_SIGNALLING_REQUEST    10016
+#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, opus_check_int(x)
+
+#define CELT_SET_TONALITY_REQUEST    10018
+#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, opus_check_int(x)
+#define CELT_SET_TONALITY_SLOPE_REQUEST    10020
+#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, opus_check_int(x)
+
+#define CELT_SET_ANALYSIS_REQUEST    10022
+#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, celt_check_analysis_ptr(x)
+
+#define OPUS_SET_LFE_REQUEST    10024
+#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, opus_check_int(x)
+
+#define OPUS_SET_ENERGY_MASK_REQUEST    10026
+#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, celt_check_glog_ptr(x)
+
+#define CELT_SET_SILK_INFO_REQUEST    10028
+#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, celt_check_silkinfo_ptr(x)
+
+
+static OPUS_INLINE opus_int32 bits_to_bitrate(opus_int32 bits, opus_int32 Fs, opus_int32 frame_size) {
+   return bits*(6*Fs/frame_size)/6;
+}
+
+static OPUS_INLINE opus_int32 bitrate_to_bits(opus_int32 bitrate, opus_int32 Fs, opus_int32 frame_size) {
+   return bitrate*6/(6*Fs/frame_size);
+}
+
+/* Encoder stuff */
+
+int celt_encoder_get_size(int channels);
+
+int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
+
+int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
+                      int arch);
+
+
+
+/* Decoder stuff */
+
+int celt_decoder_get_size(int channels);
+
+
+int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
+
+int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+      int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
+#ifdef ENABLE_DEEP_PLC
+      ,LPCNetPLCState *lpcnet
+#endif
+      ARG_QEXT(const unsigned char *qext_payload) ARG_QEXT(int qext_payload_len)
+      );
+
+int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data,
+      int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum);
+
+#define celt_encoder_ctl opus_custom_encoder_ctl
+#define celt_decoder_ctl opus_custom_decoder_ctl
+
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+#define OPUS_CUSTOM_NOSTATIC
+#else
+#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE
+#endif
+
+static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
+/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
+static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
+
+static const unsigned char tapset_icdf[3]={2,1,0};
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+static const unsigned char toOpusTable[20] = {
+      0xE0, 0xE8, 0xF0, 0xF8,
+      0xC0, 0xC8, 0xD0, 0xD8,
+      0xA0, 0xA8, 0xB0, 0xB8,
+      0x00, 0x00, 0x00, 0x00,
+      0x80, 0x88, 0x90, 0x98,
+};
+
+static const unsigned char fromOpusTable[16] = {
+      0x80, 0x88, 0x90, 0x98,
+      0x40, 0x48, 0x50, 0x58,
+      0x20, 0x28, 0x30, 0x38,
+      0x00, 0x08, 0x10, 0x18
+};
+
+static OPUS_INLINE int toOpus(unsigned char c)
+{
+   int ret=0;
+   if (c<0xA0)
+      ret = toOpusTable[c>>3];
+   if (ret == 0)
+      return -1;
+   else
+      return ret|(c&0x7);
+}
+
+static OPUS_INLINE int fromOpus(unsigned char c)
+{
+   if (c<0x80)
+      return -1;
+   else
+      return fromOpusTable[(c>>3)-16] | (c&0x7);
+}
+#endif /* CUSTOM_MODES */
+
+#define COMBFILTER_MAXPERIOD 1024
+#define COMBFILTER_MINPERIOD 15
+
+extern const signed char tf_select_table[4][8];
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+void validate_celt_decoder(CELTDecoder *st);
+#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
+#else
+#define VALIDATE_CELT_DECODER(st)
+#endif
+
+int resampling_factor(opus_int32 rate);
+
+void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
+                        int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
+
+void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+      opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+      const celt_coef *window, int overlap, int arch);
+
+void init_caps(const CELTMode *m,int *cap,int LM,int C);
+
+#ifdef RESYNTH
+void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum);
+void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
+      celt_glog *oldBandE, int start, int effEnd, int C, int CC, int isTransient,
+      int LM, int downsample, int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end));
+#endif
+
+#ifdef ENABLE_QEXT
+#define QEXT_SCALE(x) ((qext_scale)*(x))
+#define QEXT_SCALE2(x, qext_scale) ((qext_scale)*(x))
+#else
+#define QEXT_SCALE(x) (x)
+#define QEXT_SCALE2(x, qext_scale) (x)
+#endif
+
+#endif /* CELT_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_decoder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_decoder.c
new file mode 100644 (file)
index 0000000..aba91c1
--- /dev/null
@@ -0,0 +1,1872 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2010 Xiph.Org Foundation
+   Copyright (c) 2008 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CELT_DECODER_C
+
+#include "cpu_support.h"
+#include "os_support.h"
+#include "mdct.h"
+#include <math.h>
+#include "celt.h"
+#include "pitch.h"
+#include "bands.h"
+#include "modes.h"
+#include "entcode.h"
+#include "quant_bands.h"
+#include "rate.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "float_cast.h"
+#include <stdarg.h>
+#include "celt_lpc.h"
+#include "vq.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#include "lpcnet_private.h"
+#endif
+
+/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
+   CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
+   current value corresponds to a pitch of 66.67 Hz. */
+#define PLC_PITCH_LAG_MAX (720)
+/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
+   pitch of 480 Hz. */
+#define PLC_PITCH_LAG_MIN (100)
+
+#define FRAME_NONE         0
+#define FRAME_NORMAL       1
+#define FRAME_PLC_NOISE    2
+#define FRAME_PLC_PERIODIC 3
+#define FRAME_PLC_NEURAL   4
+#define FRAME_DRED         5
+
+/**********************************************************************/
+/*                                                                    */
+/*                             DECODER                                */
+/*                                                                    */
+/**********************************************************************/
+#define DECODE_BUFFER_SIZE DEC_PITCH_BUF_SIZE
+
+#define PLC_UPDATE_FRAMES 4
+#define PLC_UPDATE_SAMPLES (PLC_UPDATE_FRAMES*FRAME_SIZE)
+
+/** Decoder state
+ @brief Decoder state
+ */
+struct OpusCustomDecoder {
+   const OpusCustomMode *mode;
+   int overlap;
+   int channels;
+   int stream_channels;
+
+   int downsample;
+   int start, end;
+   int signalling;
+   int disable_inv;
+   int complexity;
+   int arch;
+#ifdef ENABLE_QEXT
+   int qext_scale;
+#endif
+
+   /* Everything beyond this point gets cleared on a reset */
+#define DECODER_RESET_START rng
+
+   opus_uint32 rng;
+   int error;
+   int last_pitch_index;
+   int loss_duration;
+   int plc_duration;
+   int last_frame_type;
+   int skip_plc;
+   int postfilter_period;
+   int postfilter_period_old;
+   opus_val16 postfilter_gain;
+   opus_val16 postfilter_gain_old;
+   int postfilter_tapset;
+   int postfilter_tapset_old;
+   int prefilter_and_fold;
+
+   celt_sig preemph_memD[2];
+
+#ifdef ENABLE_DEEP_PLC
+   opus_int16 plc_pcm[PLC_UPDATE_SAMPLES];
+   int plc_fill;
+   float plc_preemphasis_mem;
+#endif
+
+#ifdef ENABLE_QEXT
+   celt_glog qext_oldBandE[2*NB_QEXT_BANDS];
+#endif
+
+   celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
+   /* celt_glog oldEBands[], Size = 2*mode->nbEBands */
+   /* celt_glog oldLogE[], Size = 2*mode->nbEBands */
+   /* celt_glog oldLogE2[], Size = 2*mode->nbEBands */
+   /* celt_glog backgroundLogE[], Size = 2*mode->nbEBands */
+   /* opus_val16 lpc[],  Size = channels*CELT_LPC_ORDER */
+};
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+/* Make basic checks on the CELT state to ensure we don't end
+   up writing all over memory. */
+void validate_celt_decoder(CELTDecoder *st)
+{
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+   celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
+   celt_assert(st->overlap == 120);
+   celt_assert(st->end <= 21);
+#else
+/* From Section 4.3 in the spec: "The normal CELT layer uses 21 of those bands,
+   though Opus Custom (see Section 6.2) may use a different number of bands"
+
+   Check if it's within the maximum number of Bark frequency bands instead */
+   celt_assert(st->end <= 25);
+#endif
+   celt_assert(st->channels == 1 || st->channels == 2);
+   celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+   celt_assert(st->downsample > 0);
+   celt_assert(st->start == 0 || st->start == 17);
+   celt_assert(st->start < st->end);
+#ifdef OPUS_ARCHMASK
+   celt_assert(st->arch >= 0);
+   celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+#ifndef ENABLE_QEXT
+   celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
+   celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
+#endif
+   celt_assert(st->postfilter_period < MAX_PERIOD);
+   celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
+   celt_assert(st->postfilter_period_old < MAX_PERIOD);
+   celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
+   celt_assert(st->postfilter_tapset <= 2);
+   celt_assert(st->postfilter_tapset >= 0);
+   celt_assert(st->postfilter_tapset_old <= 2);
+   celt_assert(st->postfilter_tapset_old >= 0);
+}
+#endif
+
+int celt_decoder_get_size(int channels)
+{
+#ifdef ENABLE_QEXT
+   const CELTMode *mode = opus_custom_mode_create(96000, 960, NULL);
+#else
+   const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
+#endif
+   return opus_custom_decoder_get_size(mode, channels);
+}
+
+OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
+{
+   int size;
+#ifdef ENABLE_QEXT
+   int qext_scale;
+   if (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) {
+      qext_scale = 2;
+   } else qext_scale = 1;
+#endif
+   size = sizeof(struct CELTDecoder)
+            + (channels*(QEXT_SCALE(DECODE_BUFFER_SIZE)+mode->overlap)-1)*sizeof(celt_sig)
+            + 4*2*mode->nbEBands*sizeof(celt_glog)
+            + channels*CELT_LPC_ORDER*sizeof(opus_val16);
+   return size;
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
+{
+   int ret;
+   CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
+   ret = opus_custom_decoder_init(st, mode, channels);
+   if (ret != OPUS_OK)
+   {
+      opus_custom_decoder_destroy(st);
+      st = NULL;
+   }
+   if (error)
+      *error = ret;
+   return st;
+}
+#endif /* CUSTOM_MODES */
+
+int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
+{
+   int ret;
+#ifdef ENABLE_QEXT
+   if (sampling_rate == 96000) {
+      return opus_custom_decoder_init(st, opus_custom_mode_create(96000, 960, NULL), channels);
+   }
+#endif
+   ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
+   if (ret != OPUS_OK)
+      return ret;
+   st->downsample = resampling_factor(sampling_rate);
+   if (st->downsample==0)
+      return OPUS_BAD_ARG;
+   else
+      return OPUS_OK;
+}
+
+OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
+{
+   if (channels < 0 || channels > 2)
+      return OPUS_BAD_ARG;
+
+   if (st==NULL)
+      return OPUS_ALLOC_FAIL;
+
+   OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
+
+   st->mode = mode;
+   st->overlap = mode->overlap;
+   st->stream_channels = st->channels = channels;
+
+   st->downsample = 1;
+   st->start = 0;
+   st->end = st->mode->effEBands;
+   st->signalling = 1;
+#ifndef DISABLE_UPDATE_DRAFT
+   st->disable_inv = channels == 1;
+#else
+   st->disable_inv = 0;
+#endif
+   st->arch = opus_select_arch();
+
+#ifdef ENABLE_QEXT
+   if (st->mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) st->qext_scale = 2;
+   else st->qext_scale = 1;
+#endif
+
+   opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
+
+   return OPUS_OK;
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+void opus_custom_decoder_destroy(CELTDecoder *st)
+{
+   opus_free(st);
+}
+#endif /* CUSTOM_MODES */
+
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+/* Special case for stereo with no downsampling and no accumulation. This is
+   quite common and we can make it faster by processing both channels in the
+   same loop, reducing overhead due to the dependency loop in the IIR filter. */
+static void deemphasis_stereo_simple(celt_sig *in[], opus_res *pcm, int N, const opus_val16 coef0,
+      celt_sig *mem)
+{
+   celt_sig * OPUS_RESTRICT x0;
+   celt_sig * OPUS_RESTRICT x1;
+   celt_sig m0, m1;
+   int j;
+   x0=in[0];
+   x1=in[1];
+   m0 = mem[0];
+   m1 = mem[1];
+   for (j=0;j<N;j++)
+   {
+      celt_sig tmp0, tmp1;
+      /* Add VERY_SMALL to x[] first to reduce dependency chain. */
+      tmp0 = SATURATE(x0[j] + VERY_SMALL + m0, SIG_SAT);
+      tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT);
+      m0 = MULT16_32_Q15(coef0, tmp0);
+      m1 = MULT16_32_Q15(coef0, tmp1);
+      pcm[2*j  ] = SIG2RES(tmp0);
+      pcm[2*j+1] = SIG2RES(tmp1);
+   }
+   mem[0] = m0;
+   mem[1] = m1;
+}
+#endif
+
+#ifndef RESYNTH
+static
+#endif
+void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef,
+      celt_sig *mem, int accum)
+{
+   int c;
+   int Nd;
+   int apply_downsampling=0;
+   opus_val16 coef0;
+   VARDECL(celt_sig, scratch);
+   SAVE_STACK;
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+   /* Short version for common case. */
+   if (downsample == 1 && C == 2 && !accum)
+   {
+      deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
+      return;
+   }
+#endif
+   ALLOC(scratch, N, celt_sig);
+   coef0 = coef[0];
+   Nd = N/downsample;
+   c=0; do {
+      int j;
+      celt_sig * OPUS_RESTRICT x;
+      opus_res  * OPUS_RESTRICT y;
+      celt_sig m = mem[c];
+      x =in[c];
+      y = pcm+c;
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) || defined(ENABLE_QEXT)
+      if (coef[1] != 0)
+      {
+         opus_val16 coef1 = coef[1];
+         opus_val16 coef3 = coef[3];
+         for (j=0;j<N;j++)
+         {
+            celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
+            m = MULT16_32_Q15(coef0, tmp)
+                          - MULT16_32_Q15(coef1, x[j]);
+            tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
+            scratch[j] = tmp;
+         }
+         apply_downsampling=1;
+      } else
+#endif
+      if (downsample>1)
+      {
+         /* Shortcut for the standard (non-custom modes) case */
+         for (j=0;j<N;j++)
+         {
+            celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
+            m = MULT16_32_Q15(coef0, tmp);
+            scratch[j] = tmp;
+         }
+         apply_downsampling=1;
+      } else {
+         /* Shortcut for the standard (non-custom modes) case */
+         if (accum)
+         {
+            for (j=0;j<N;j++)
+            {
+               celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
+               m = MULT16_32_Q15(coef0, tmp);
+               y[j*C] = ADD_RES(y[j*C], SIG2RES(tmp));
+            }
+         } else
+         {
+            for (j=0;j<N;j++)
+            {
+               celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
+               m = MULT16_32_Q15(coef0, tmp);
+               y[j*C] = SIG2RES(tmp);
+            }
+         }
+      }
+      mem[c] = m;
+
+      if (apply_downsampling)
+      {
+         /* Perform down-sampling */
+         if (accum)
+         {
+            for (j=0;j<Nd;j++)
+               y[j*C] = ADD_RES(y[j*C], SIG2RES(scratch[j*downsample]));
+         } else
+         {
+            for (j=0;j<Nd;j++)
+               y[j*C] = SIG2RES(scratch[j*downsample]);
+         }
+      }
+   } while (++c<C);
+   RESTORE_STACK;
+}
+
+#ifndef RESYNTH
+static
+#endif
+void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
+                    celt_glog *oldBandE, int start, int effEnd, int C, int CC,
+                    int isTransient, int LM, int downsample,
+                    int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end))
+{
+   int c, i;
+   int M;
+   int b;
+   int B;
+   int N, NB;
+   int shift;
+   int nbEBands;
+   int overlap;
+   VARDECL(celt_sig, freq);
+   SAVE_STACK;
+
+   overlap = mode->overlap;
+   nbEBands = mode->nbEBands;
+   N = mode->shortMdctSize<<LM;
+   ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
+   M = 1<<LM;
+#ifdef ENABLE_QEXT
+   if (mode->Fs != 96000) qext_end=2;
+#endif
+
+   if (isTransient)
+   {
+      B = M;
+      NB = mode->shortMdctSize;
+      shift = mode->maxLM;
+   } else {
+      B = 1;
+      NB = mode->shortMdctSize<<LM;
+      shift = mode->maxLM-LM;
+   }
+
+   if (CC==2&&C==1)
+   {
+      /* Copying a mono streams to two channels */
+      celt_sig *freq2;
+      denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
+            downsample, silence);
+#ifdef ENABLE_QEXT
+      if (qext_mode)
+         denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
+                        downsample, silence);
+#endif
+      /* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
+      freq2 = out_syn[1]+overlap/2;
+      OPUS_COPY(freq2, freq, N);
+      for (b=0;b<B;b++)
+         clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
+      for (b=0;b<B;b++)
+         clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
+   } else if (CC==1&&C==2)
+   {
+      /* Downmixing a stereo stream to mono */
+      celt_sig *freq2;
+      freq2 = out_syn[0]+overlap/2;
+      denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
+            downsample, silence);
+      /* Use the output buffer as temp array before downmixing. */
+      denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
+            downsample, silence);
+#ifdef ENABLE_QEXT
+      if (qext_mode)
+      {
+         denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
+                        downsample, silence);
+         denormalise_bands(qext_mode, X+N, freq2, qext_bandLogE+NB_QEXT_BANDS, 0, qext_end, M,
+                        downsample, silence);
+      }
+#endif
+      for (i=0;i<N;i++)
+         freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
+      for (b=0;b<B;b++)
+         clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
+   } else {
+      /* Normal case (mono or stereo) */
+      c=0; do {
+         denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
+               downsample, silence);
+#ifdef ENABLE_QEXT
+         if (qext_mode)
+            denormalise_bands(qext_mode, X+c*N, freq, qext_bandLogE+c*NB_QEXT_BANDS, 0, qext_end, M,
+                           downsample, silence);
+#endif
+         for (b=0;b<B;b++)
+            clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
+      } while (++c<CC);
+   }
+   /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
+      or in the */
+   c=0; do {
+      for (i=0;i<N;i++)
+         out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
+   } while (++c<CC);
+   RESTORE_STACK;
+}
+
+static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
+{
+   int i, curr, tf_select;
+   int tf_select_rsv;
+   int tf_changed;
+   int logp;
+   opus_uint32 budget;
+   opus_uint32 tell;
+
+   budget = dec->storage*8;
+   tell = ec_tell(dec);
+   logp = isTransient ? 2 : 4;
+   tf_select_rsv = LM>0 && tell+logp+1<=budget;
+   budget -= tf_select_rsv;
+   tf_changed = curr = 0;
+   for (i=start;i<end;i++)
+   {
+      if (tell+logp<=budget)
+      {
+         curr ^= ec_dec_bit_logp(dec, logp);
+         tell = ec_tell(dec);
+         tf_changed |= curr;
+      }
+      tf_res[i] = curr;
+      logp = isTransient ? 4 : 5;
+   }
+   tf_select = 0;
+   if (tf_select_rsv &&
+     tf_select_table[LM][4*isTransient+0+tf_changed] !=
+     tf_select_table[LM][4*isTransient+2+tf_changed])
+   {
+      tf_select = ec_dec_bit_logp(dec, 1);
+   }
+   for (i=start;i<end;i++)
+   {
+      tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
+   }
+}
+
+static int celt_plc_pitch_search(CELTDecoder *st, celt_sig *decode_mem[2], int C, int arch)
+{
+   int pitch_index;
+#ifdef ENABLE_QEXT
+   int qext_scale;
+#endif
+   VARDECL( opus_val16, lp_pitch_buf );
+   SAVE_STACK;
+#ifdef ENABLE_QEXT
+   qext_scale = st->qext_scale;
+#else
+   (void)st;
+#endif
+   ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
+   pitch_downsample(decode_mem, lp_pitch_buf,
+         DECODE_BUFFER_SIZE>>1, C, QEXT_SCALE(2), arch);
+   pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
+         DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
+         PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
+   pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
+   RESTORE_STACK;
+   return QEXT_SCALE(pitch_index);
+}
+
+static void prefilter_and_fold(CELTDecoder * OPUS_RESTRICT st, int N)
+{
+   int c;
+   int CC;
+   int i;
+   int overlap;
+   celt_sig *decode_mem[2];
+   const OpusCustomMode *mode;
+   int decode_buffer_size;
+#ifdef ENABLE_QEXT
+   int qext_scale;
+#endif
+   VARDECL(opus_val32, etmp);
+   SAVE_STACK
+#ifdef ENABLE_QEXT
+   qext_scale = st->qext_scale;
+#endif
+   decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+   mode = st->mode;
+   overlap = st->overlap;
+   CC = st->channels;
+   ALLOC(etmp, overlap, opus_val32);
+   c=0; do {
+      decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+   } while (++c<CC);
+
+   c=0; do {
+      /* Apply the pre-filter to the MDCT overlap for the next frame because
+         the post-filter will be re-applied in the decoder after the MDCT
+         overlap. */
+      comb_filter(etmp, decode_mem[c]+decode_buffer_size-N,
+         st->postfilter_period_old, st->postfilter_period, overlap,
+         -st->postfilter_gain_old, -st->postfilter_gain,
+         st->postfilter_tapset_old, st->postfilter_tapset, NULL, 0, st->arch);
+
+      /* Simulate TDAC on the concealed audio so that it blends with the
+         MDCT of the next frame. */
+      for (i=0;i<overlap/2;i++)
+      {
+         decode_mem[c][decode_buffer_size-N+i] =
+            MULT16_32_Q15(COEF2VAL16(mode->window[i]), etmp[overlap-1-i])
+            + MULT16_32_Q15 (COEF2VAL16(mode->window[overlap-i-1]), etmp[i]);
+      }
+   } while (++c<CC);
+   RESTORE_STACK;
+}
+
+#ifdef ENABLE_DEEP_PLC
+
+#define SINC_ORDER 48
+/* h=cos(pi/2*abs(sin([-24:24]/48*pi*23./24)).^2);
+   b=sinc([-24:24]/3*1.02).*h;
+   b=b/sum(b); */
+static const float sinc_filter[SINC_ORDER+1] = {
+    4.2931e-05f, -0.000190293f, -0.000816132f, -0.000637162f, 0.00141662f, 0.00354764f, 0.00184368f, -0.00428274f,
+    -0.00856105f, -0.0034003f, 0.00930201f, 0.0159616f, 0.00489785f, -0.0169649f, -0.0259484f, -0.00596856f,
+    0.0286551f, 0.0405872f, 0.00649994f, -0.0509284f, -0.0716655f, -0.00665212f,  0.134336f,  0.278927f,
+    0.339995f,  0.278927f,  0.134336f, -0.00665212f, -0.0716655f, -0.0509284f, 0.00649994f, 0.0405872f,
+    0.0286551f, -0.00596856f, -0.0259484f, -0.0169649f, 0.00489785f, 0.0159616f, 0.00930201f, -0.0034003f,
+    -0.00856105f, -0.00428274f, 0.00184368f, 0.00354764f, 0.00141662f, -0.000637162f, -0.000816132f, -0.000190293f,
+    4.2931e-05f
+};
+
+void update_plc_state(LPCNetPLCState *lpcnet, celt_sig *decode_mem[2], float *plc_preemphasis_mem, int CC)
+{
+   int i;
+   int tmp_read_post, tmp_fec_skip;
+   int offset;
+   celt_sig buf48k[DECODE_BUFFER_SIZE];
+   opus_int16 buf16k[PLC_UPDATE_SAMPLES];
+   if (CC == 1) OPUS_COPY(buf48k, decode_mem[0], DECODE_BUFFER_SIZE);
+   else {
+      for (i=0;i<DECODE_BUFFER_SIZE;i++) {
+         buf48k[i] = .5*(decode_mem[0][i] + decode_mem[1][i]);
+      }
+   }
+   /* Down-sample the last 40 ms. */
+   for (i=1;i<DECODE_BUFFER_SIZE;i++) buf48k[i] += PREEMPHASIS*buf48k[i-1];
+   *plc_preemphasis_mem = buf48k[DECODE_BUFFER_SIZE-1];
+   offset = DECODE_BUFFER_SIZE-SINC_ORDER-1 - 3*(PLC_UPDATE_SAMPLES-1);
+   celt_assert(3*(PLC_UPDATE_SAMPLES-1) + SINC_ORDER + offset == DECODE_BUFFER_SIZE-1);
+   for (i=0;i<PLC_UPDATE_SAMPLES;i++) {
+      int j;
+      float sum = 0;
+      for (j=0;j<SINC_ORDER+1;j++) {
+         sum += buf48k[3*i + j + offset]*sinc_filter[j];
+      }
+      buf16k[i] = float2int(MIN32(32767.f, MAX32(-32767.f, sum)));
+   }
+   tmp_read_post = lpcnet->fec_read_pos;
+   tmp_fec_skip = lpcnet->fec_skip;
+   for (i=0;i<PLC_UPDATE_FRAMES;i++) {
+      lpcnet_plc_update(lpcnet, &buf16k[FRAME_SIZE*i]);
+   }
+   lpcnet->fec_read_pos = tmp_read_post;
+   lpcnet->fec_skip = tmp_fec_skip;
+}
+#endif
+
+static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
+#ifdef ENABLE_DEEP_PLC
+      ,LPCNetPLCState *lpcnet
+#endif
+      )
+{
+   int c;
+   int i;
+   const int C = st->channels;
+   celt_sig *decode_mem[2];
+   celt_sig *out_syn[2];
+   opus_val16 *lpc;
+   celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
+   const OpusCustomMode *mode;
+   int nbEBands;
+   int overlap;
+   int start;
+   int loss_duration;
+   int curr_frame_type;
+   const opus_int16 *eBands;
+   int decode_buffer_size;
+   int max_period;
+#ifdef ENABLE_QEXT
+   int qext_scale;
+#endif
+   SAVE_STACK;
+#ifdef ENABLE_QEXT
+   qext_scale = st->qext_scale;
+#endif
+   decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+   max_period = QEXT_SCALE(MAX_PERIOD);
+   mode = st->mode;
+   nbEBands = mode->nbEBands;
+   overlap = mode->overlap;
+   eBands = mode->eBands;
+
+   c=0; do {
+      decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+      out_syn[c] = decode_mem[c]+decode_buffer_size-N;
+   } while (++c<C);
+   oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+overlap)*C);
+   oldLogE = oldBandE + 2*nbEBands;
+   oldLogE2 = oldLogE + 2*nbEBands;
+   backgroundLogE = oldLogE2 + 2*nbEBands;
+   lpc = (opus_val16*)(backgroundLogE + 2*nbEBands);
+
+   loss_duration = st->loss_duration;
+   start = st->start;
+   curr_frame_type = FRAME_PLC_PERIODIC;
+   if (st->plc_duration >= 40 || start != 0 || st->skip_plc)
+      curr_frame_type = FRAME_PLC_NOISE;
+#ifdef ENABLE_DEEP_PLC
+   if (start == 0 && lpcnet != NULL && st->mode->Fs != 96000 && lpcnet->loaded)
+   {
+      if (st->complexity >= 5 && st->plc_duration < 80 && !st->skip_plc)
+         curr_frame_type = FRAME_PLC_NEURAL;
+#ifdef ENABLE_DRED
+      if (lpcnet->fec_fill_pos > lpcnet->fec_read_pos)
+         curr_frame_type = FRAME_DRED;
+#endif
+   }
+#endif
+
+   if (curr_frame_type == FRAME_PLC_NOISE)
+   {
+      /* Noise-based PLC/CNG */
+      VARDECL(celt_norm, X);
+      opus_uint32 seed;
+      int end;
+      int effEnd;
+      celt_glog decay;
+      end = st->end;
+      effEnd = IMAX(start, IMIN(end, mode->effEBands));
+
+      ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
+      c=0; do {
+         OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
+               decode_buffer_size-N+overlap);
+      } while (++c<C);
+
+      if (st->prefilter_and_fold) {
+         prefilter_and_fold(st, N);
+      }
+
+      /* Energy decay */
+      decay = loss_duration==0 ? GCONST(1.5f) : GCONST(.5f);
+      c=0; do
+      {
+         for (i=start;i<end;i++)
+            oldBandE[c*nbEBands+i] = MAXG(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
+      } while (++c<C);
+      seed = st->rng;
+      for (c=0;c<C;c++)
+      {
+         for (i=start;i<effEnd;i++)
+         {
+            int j;
+            int boffs;
+            int blen;
+            boffs = N*c+(eBands[i]<<LM);
+            blen = (eBands[i+1]-eBands[i])<<LM;
+            for (j=0;j<blen;j++)
+            {
+               seed = celt_lcg_rand(seed);
+               X[boffs+j] = SHL32((celt_norm)((opus_int32)seed>>20), NORM_SHIFT-14);
+            }
+            renormalise_vector(X+boffs, blen, Q31ONE, st->arch);
+         }
+      }
+      st->rng = seed;
+
+      celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch ARG_QEXT(NULL) ARG_QEXT(NULL) ARG_QEXT(0));
+
+      /* Run the postfilter with the last parameters. */
+      c=0; do {
+         st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
+         st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
+         comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
+               st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
+               mode->window, overlap, st->arch);
+         if (LM!=0)
+            comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, st->postfilter_period, N-mode->shortMdctSize,
+                  st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
+                  mode->window, overlap, st->arch);
+
+      } while (++c<C);
+      st->postfilter_period_old = st->postfilter_period;
+      st->postfilter_gain_old = st->postfilter_gain;
+      st->postfilter_tapset_old = st->postfilter_tapset;
+
+      st->prefilter_and_fold = 0;
+      /* Skip regular PLC until we get two consecutive packets. */
+      st->skip_plc = 1;
+   } else {
+      int exc_length;
+      /* Pitch-based PLC */
+      const celt_coef *window;
+      opus_val16 *exc;
+      opus_val16 fade = Q15ONE;
+      int pitch_index;
+      int curr_neural;
+      int last_neural;
+      VARDECL(opus_val16, _exc);
+      VARDECL(opus_val16, fir_tmp);
+
+      curr_neural = curr_frame_type == FRAME_PLC_NEURAL || curr_frame_type == FRAME_DRED;
+      last_neural = st->last_frame_type == FRAME_PLC_NEURAL || st->last_frame_type == FRAME_DRED;
+      if (st->last_frame_type != FRAME_PLC_PERIODIC && !(last_neural && curr_neural))
+      {
+         st->last_pitch_index = pitch_index = celt_plc_pitch_search(st, decode_mem, C, st->arch);
+      } else {
+         pitch_index = st->last_pitch_index;
+         fade = QCONST16(.8f,15);
+      }
+#ifdef ENABLE_DEEP_PLC
+      if (curr_neural && !last_neural) update_plc_state(lpcnet, decode_mem, &st->plc_preemphasis_mem, C);
+#endif
+
+      /* We want the excitation for 2 pitch periods in order to look for a
+         decaying signal, but we can't get more than MAX_PERIOD. */
+      exc_length = IMIN(2*pitch_index, max_period);
+
+      ALLOC(_exc, max_period+CELT_LPC_ORDER, opus_val16);
+      ALLOC(fir_tmp, exc_length, opus_val16);
+      exc = _exc+CELT_LPC_ORDER;
+      window = mode->window;
+      c=0; do {
+         opus_val16 decay;
+         opus_val16 attenuation;
+         opus_val32 S1=0;
+         celt_sig *buf;
+         int extrapolation_offset;
+         int extrapolation_len;
+         int j;
+
+         buf = decode_mem[c];
+         for (i=0;i<max_period+CELT_LPC_ORDER;i++)
+            exc[i-CELT_LPC_ORDER] = SROUND16(buf[decode_buffer_size-max_period-CELT_LPC_ORDER+i], SIG_SHIFT);
+
+         if (st->last_frame_type != FRAME_PLC_PERIODIC && !(last_neural && curr_neural))
+         {
+            opus_val32 ac[CELT_LPC_ORDER+1];
+            /* Compute LPC coefficients for the last MAX_PERIOD samples before
+               the first loss so we can work in the excitation-filter domain. */
+            _celt_autocorr(exc, ac, window, overlap,
+                   CELT_LPC_ORDER, max_period, st->arch);
+            /* Add a noise floor of -40 dB. */
+#ifdef FIXED_POINT
+            ac[0] += SHR32(ac[0],13);
+#else
+            ac[0] *= 1.0001f;
+#endif
+            /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
+            for (i=1;i<=CELT_LPC_ORDER;i++)
+            {
+               /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+#ifdef FIXED_POINT
+               ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+#else
+               ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
+#endif
+            }
+            _celt_lpc(lpc+c*CELT_LPC_ORDER, ac, CELT_LPC_ORDER);
+#ifdef FIXED_POINT
+         /* For fixed-point, apply bandwidth expansion until we can guarantee that
+            no overflow can happen in the IIR filter. This means:
+            32768*sum(abs(filter)) < 2^31 */
+         while (1) {
+            opus_val16 tmp=Q15ONE;
+            opus_val32 sum=QCONST16(1., SIG_SHIFT);
+            for (i=0;i<CELT_LPC_ORDER;i++)
+               sum += ABS16(lpc[c*CELT_LPC_ORDER+i]);
+            if (sum < 65535) break;
+            for (i=0;i<CELT_LPC_ORDER;i++)
+            {
+               tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
+               lpc[c*CELT_LPC_ORDER+i] = MULT16_16_Q15(lpc[c*CELT_LPC_ORDER+i], tmp);
+            }
+         }
+#endif
+         }
+         /* Initialize the LPC history with the samples just before the start
+            of the region for which we're computing the excitation. */
+         {
+            /* Compute the excitation for exc_length samples before the loss. We need the copy
+               because celt_fir() cannot filter in-place. */
+            celt_fir(exc+max_period-exc_length, lpc+c*CELT_LPC_ORDER,
+                  fir_tmp, exc_length, CELT_LPC_ORDER, st->arch);
+            OPUS_COPY(exc+max_period-exc_length, fir_tmp, exc_length);
+         }
+
+         /* Check if the waveform is decaying, and if so how fast.
+            We do this to avoid adding energy when concealing in a segment
+            with decaying energy. */
+         {
+            opus_val32 E1=1, E2=1;
+            int decay_length;
+#ifdef FIXED_POINT
+            int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[max_period-exc_length], exc_length))-20);
+#ifdef ENABLE_QEXT
+            if (st->qext_scale==2) shift++;
+#endif
+#endif
+            decay_length = exc_length>>1;
+            for (i=0;i<decay_length;i++)
+            {
+               opus_val16 e;
+               e = exc[max_period-decay_length+i];
+               E1 += SHR32(MULT16_16(e, e), shift);
+               e = exc[max_period-2*decay_length+i];
+               E2 += SHR32(MULT16_16(e, e), shift);
+            }
+            E1 = MIN32(E1, E2);
+            decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
+         }
+
+         /* Move the decoder memory one frame to the left to give us room to
+            add the data for the new frame. We ignore the overlap that extends
+            past the end of the buffer, because we aren't going to use it. */
+         OPUS_MOVE(buf, buf+N, decode_buffer_size-N);
+
+         /* Extrapolate from the end of the excitation with a period of
+            "pitch_index", scaling down each period by an additional factor of
+            "decay". */
+         extrapolation_offset = max_period-pitch_index;
+         /* We need to extrapolate enough samples to cover a complete MDCT
+            window (including overlap/2 samples on both sides). */
+         extrapolation_len = N+overlap;
+         /* We also apply fading if this is not the first loss. */
+         attenuation = MULT16_16_Q15(fade, decay);
+         for (i=j=0;i<extrapolation_len;i++,j++)
+         {
+            opus_val16 tmp;
+            if (j >= pitch_index) {
+               j -= pitch_index;
+               attenuation = MULT16_16_Q15(attenuation, decay);
+            }
+            buf[decode_buffer_size-N+i] =
+                  SHL32(EXTEND32(MULT16_16_Q15(attenuation,
+                        exc[extrapolation_offset+j])), SIG_SHIFT);
+            /* Compute the energy of the previously decoded signal whose
+               excitation we're copying. */
+            tmp = SROUND16(
+                  buf[decode_buffer_size-max_period-N+extrapolation_offset+j],
+                  SIG_SHIFT);
+            S1 += SHR32(MULT16_16(tmp, tmp), 11);
+         }
+         {
+            opus_val16 lpc_mem[CELT_LPC_ORDER];
+            /* Copy the last decoded samples (prior to the overlap region) to
+               synthesis filter memory so we can have a continuous signal. */
+            for (i=0;i<CELT_LPC_ORDER;i++)
+               lpc_mem[i] = SROUND16(buf[decode_buffer_size-N-1-i], SIG_SHIFT);
+            /* Apply the synthesis filter to convert the excitation back into
+               the signal domain. */
+            celt_iir(buf+decode_buffer_size-N, lpc+c*CELT_LPC_ORDER,
+                  buf+decode_buffer_size-N, extrapolation_len, CELT_LPC_ORDER,
+                  lpc_mem, st->arch);
+#ifdef FIXED_POINT
+            for (i=0; i < extrapolation_len; i++)
+               buf[decode_buffer_size-N+i] = SATURATE(buf[decode_buffer_size-N+i], SIG_SAT);
+#endif
+         }
+
+         /* Check if the synthesis energy is higher than expected, which can
+            happen with the signal changes during our window. If so,
+            attenuate. */
+         {
+            opus_val32 S2=0;
+            for (i=0;i<extrapolation_len;i++)
+            {
+               opus_val16 tmp = SROUND16(buf[decode_buffer_size-N+i], SIG_SHIFT);
+               S2 += SHR32(MULT16_16(tmp, tmp), 11);
+            }
+            /* This checks for an "explosion" in the synthesis. */
+#ifdef FIXED_POINT
+            if (!(S1 > SHR32(S2,2)))
+#else
+            /* The float test is written this way to catch NaNs in the output
+               of the IIR filter at the same time. */
+            if (!(S1 > 0.2f*S2))
+#endif
+            {
+               for (i=0;i<extrapolation_len;i++)
+                  buf[decode_buffer_size-N+i] = 0;
+            } else if (S1 < S2)
+            {
+               opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
+               for (i=0;i<overlap;i++)
+               {
+                  opus_val16 tmp_g = Q15ONE
+                        - MULT16_16_Q15(COEF2VAL16(window[i]), Q15ONE-ratio);
+                  buf[decode_buffer_size-N+i] =
+                        MULT16_32_Q15(tmp_g, buf[decode_buffer_size-N+i]);
+               }
+               for (i=overlap;i<extrapolation_len;i++)
+               {
+                  buf[decode_buffer_size-N+i] =
+                        MULT16_32_Q15(ratio, buf[decode_buffer_size-N+i]);
+               }
+            }
+         }
+
+      } while (++c<C);
+
+#ifdef ENABLE_DEEP_PLC
+      if (curr_neural) {
+         float overlap_mem;
+         int samples_needed16k;
+         celt_sig *buf;
+         VARDECL(float, buf_copy);
+         buf = decode_mem[0];
+         ALLOC(buf_copy, C*overlap, float);
+         c=0; do {
+            OPUS_COPY(buf_copy+c*overlap, &decode_mem[c][decode_buffer_size-N], overlap);
+         } while (++c<C);
+
+         /* Need enough samples from the PLC to cover the frame size, resampling delay,
+            and the overlap at the end. */
+         samples_needed16k = (N+SINC_ORDER+overlap)/3;
+         if (!last_neural) {
+            st->plc_fill = 0;
+         }
+         while (st->plc_fill < samples_needed16k) {
+            lpcnet_plc_conceal(lpcnet, &st->plc_pcm[st->plc_fill]);
+            st->plc_fill += FRAME_SIZE;
+         }
+         /* Resample to 48 kHz. */
+         for (i=0;i<(N+overlap)/3;i++) {
+            int j;
+            float sum;
+            for (sum=0, j=0;j<17;j++) sum += 3*st->plc_pcm[i+j]*sinc_filter[3*j];
+            buf[decode_buffer_size-N+3*i] = sum;
+            for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+2];
+            buf[decode_buffer_size-N+3*i+1] = sum;
+            for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+1];
+            buf[decode_buffer_size-N+3*i+2] = sum;
+         }
+         OPUS_MOVE(st->plc_pcm, &st->plc_pcm[N/3], st->plc_fill-N/3);
+         st->plc_fill -= N/3;
+         for (i=0;i<N;i++) {
+            float tmp = buf[decode_buffer_size-N+i];
+            buf[decode_buffer_size-N+i] -= PREEMPHASIS*st->plc_preemphasis_mem;
+            st->plc_preemphasis_mem = tmp;
+         }
+         overlap_mem = st->plc_preemphasis_mem;
+         for (i=0;i<overlap;i++) {
+            float tmp = buf[decode_buffer_size+i];
+            buf[decode_buffer_size+i] -= PREEMPHASIS*overlap_mem;
+            overlap_mem = tmp;
+         }
+         /* For now, we just do mono PLC. */
+         if (C==2) OPUS_COPY(decode_mem[1], decode_mem[0], decode_buffer_size+overlap);
+         c=0; do {
+            /* Cross-fade with 48-kHz non-neural PLC for the first 2.5 ms to avoid a discontinuity. */
+            if (!last_neural) {
+               for (i=0;i<overlap;i++) decode_mem[c][decode_buffer_size-N+i] = (1-window[i])*buf_copy[c*overlap+i] + (window[i])*decode_mem[c][decode_buffer_size-N+i];
+            }
+         } while (++c<C);
+      }
+#endif
+      st->prefilter_and_fold = 1;
+   }
+
+   /* Saturate to something large to avoid wrap-around. */
+   st->loss_duration = IMIN(10000, loss_duration+(1<<LM));
+   st->plc_duration = IMIN(10000, st->plc_duration+(1<<LM));
+#ifdef ENABLE_DRED
+   if (curr_frame_type == FRAME_DRED) {
+      st->plc_duration = 0;
+      st->skip_plc = 0;
+   }
+#endif
+   st->last_frame_type = curr_frame_type;
+   RESTORE_STACK;
+}
+
+#ifdef ENABLE_QEXT
+static void decode_qext_stereo_params(ec_dec *ec, int qext_end, int *qext_intensity, int *qext_dual_stereo) {
+   *qext_intensity = ec_dec_uint(ec, qext_end+1);
+   if (*qext_intensity != 0) *qext_dual_stereo = ec_dec_bit_logp(ec, 1);
+   else *qext_dual_stereo = 0;
+}
+#endif
+
+int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+      int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
+#ifdef ENABLE_DEEP_PLC
+      ,LPCNetPLCState *lpcnet
+#endif
+      ARG_QEXT(const unsigned char *qext_payload) ARG_QEXT(int qext_payload_len)
+      )
+{
+   int c, i, N;
+   int spread_decision;
+   opus_int32 bits;
+   ec_dec _dec;
+   VARDECL(celt_norm, X);
+   VARDECL(int, fine_quant);
+   VARDECL(int, pulses);
+   VARDECL(int, cap);
+   VARDECL(int, offsets);
+   VARDECL(int, fine_priority);
+   VARDECL(int, tf_res);
+   VARDECL(unsigned char, collapse_masks);
+   celt_sig *decode_mem[2];
+   celt_sig *out_syn[2];
+   celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
+
+   int shortBlocks;
+   int isTransient;
+   int intra_ener;
+   const int CC = st->channels;
+   int LM, M;
+   int start;
+   int end;
+   int effEnd;
+   int codedBands;
+   int alloc_trim;
+   int postfilter_pitch;
+   opus_val16 postfilter_gain;
+   int intensity=0;
+   int dual_stereo=0;
+   opus_int32 total_bits;
+   opus_int32 balance;
+   opus_int32 tell;
+   int dynalloc_logp;
+   int postfilter_tapset;
+   int anti_collapse_rsv;
+   int anti_collapse_on=0;
+   int silence;
+   int C = st->stream_channels;
+   const OpusCustomMode *mode;
+   int nbEBands;
+   int overlap;
+   const opus_int16 *eBands;
+   celt_glog max_background_increase;
+   int decode_buffer_size;
+#ifdef ENABLE_QEXT
+   opus_int32 qext_bits;
+   ec_dec ext_dec;
+   int qext_bytes=0;
+   int qext_end=0;
+   int qext_intensity=0;
+   int qext_dual_stereo=0;
+   VARDECL(int, extra_quant);
+   VARDECL(int, extra_pulses);
+   const CELTMode *qext_mode = NULL;
+   CELTMode qext_mode_struct;
+   int qext_scale;
+#else
+# define qext_bytes 0
+#endif
+   ALLOC_STACK;
+#ifdef ENABLE_QEXT
+   qext_scale = st->qext_scale;
+#endif
+   decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+
+   VALIDATE_CELT_DECODER(st);
+   mode = st->mode;
+   nbEBands = mode->nbEBands;
+   overlap = mode->overlap;
+   eBands = mode->eBands;
+   start = st->start;
+   end = st->end;
+   frame_size *= st->downsample;
+
+   oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+overlap)*CC);
+   oldLogE = oldBandE + 2*nbEBands;
+   oldLogE2 = oldLogE + 2*nbEBands;
+   backgroundLogE = oldLogE2 + 2*nbEBands;
+
+#ifdef ENABLE_QEXT
+   if (qext_payload) {
+      ec_dec_init(&ext_dec, (unsigned char*)qext_payload, qext_payload_len);
+      qext_bytes = qext_payload_len;
+   } else {
+      ec_dec_init(&ext_dec, NULL, 0);
+   }
+#endif
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+   if (st->signalling && data!=NULL)
+   {
+      int data0=data[0];
+      /* Convert "standard mode" to Opus header */
+# ifndef ENABLE_QEXT
+      if (mode->Fs==48000 && mode->shortMdctSize==120)
+# endif
+      {
+         data0 = fromOpus(data0);
+         if (data0<0)
+            return OPUS_INVALID_PACKET;
+      }
+      st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
+      LM = (data0>>3)&0x3;
+      C = 1 + ((data0>>2)&0x1);
+      if ((data[0] & 0x03) == 0x03) {
+         data++;
+         len--;
+         if (len<=0)
+            return OPUS_INVALID_PACKET;
+         if (data[0] & 0x40) {
+            int p;
+            int padding=0;
+            data++;
+            len--;
+            do {
+               int tmp;
+               if (len<=0)
+                  return OPUS_INVALID_PACKET;
+               p = *data++;
+               len--;
+               tmp = p==255 ? 254: p;
+               len -= tmp;
+               padding += tmp;
+            } while (p==255);
+            padding--;
+            if (len <= 0 || padding<0) return OPUS_INVALID_PACKET;
+#ifdef ENABLE_QEXT
+            qext_bytes = padding;
+            if (data[len] != QEXT_EXTENSION_ID<<1)
+               qext_bytes=0;
+            ec_dec_init(&ext_dec, (unsigned char*)data+len+1, qext_bytes);
+#endif
+         }
+      } else
+      {
+         data++;
+         len--;
+      }
+      if (LM>mode->maxLM)
+         return OPUS_INVALID_PACKET;
+      if (frame_size < mode->shortMdctSize<<LM)
+         return OPUS_BUFFER_TOO_SMALL;
+      else
+         frame_size = mode->shortMdctSize<<LM;
+   } else {
+#else
+   {
+#endif
+      for (LM=0;LM<=mode->maxLM;LM++)
+         if (mode->shortMdctSize<<LM==frame_size)
+            break;
+      if (LM>mode->maxLM)
+         return OPUS_BAD_ARG;
+   }
+   M=1<<LM;
+
+   if (len<0 || len>1275 || pcm==NULL)
+      return OPUS_BAD_ARG;
+
+   N = M*mode->shortMdctSize;
+   c=0; do {
+      decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+      out_syn[c] = decode_mem[c]+decode_buffer_size-N;
+   } while (++c<CC);
+
+   effEnd = end;
+   if (effEnd > mode->effEBands)
+      effEnd = mode->effEBands;
+
+   if (data == NULL || len<=1)
+   {
+      celt_decode_lost(st, N, LM
+#ifdef ENABLE_DEEP_PLC
+      , lpcnet
+#endif
+                      );
+      deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
+      RESTORE_STACK;
+      return frame_size/st->downsample;
+   }
+#ifdef ENABLE_DEEP_PLC
+   else {
+      /* FIXME: This is a bit of a hack just to make sure opus_decode_native() knows we're no longer in PLC. */
+      if (lpcnet) lpcnet->blend = 0;
+   }
+#endif
+
+   /* Check if there are at least two packets received consecutively before
+    * turning on the pitch-based PLC */
+   if (st->loss_duration == 0) st->skip_plc = 0;
+
+   if (dec == NULL)
+   {
+      ec_dec_init(&_dec,(unsigned char*)data,len);
+      dec = &_dec;
+   }
+
+   if (C==1)
+   {
+      for (i=0;i<nbEBands;i++)
+         oldBandE[i]=MAXG(oldBandE[i],oldBandE[nbEBands+i]);
+   }
+
+   total_bits = len*8;
+   tell = ec_tell(dec);
+
+   if (tell >= total_bits)
+      silence = 1;
+   else if (tell==1)
+      silence = ec_dec_bit_logp(dec, 15);
+   else
+      silence = 0;
+   if (silence)
+   {
+      /* Pretend we've read all the remaining bits */
+      tell = len*8;
+      dec->nbits_total+=tell-ec_tell(dec);
+   }
+
+   postfilter_gain = 0;
+   postfilter_pitch = 0;
+   postfilter_tapset = 0;
+   if (start==0 && tell+16 <= total_bits)
+   {
+      if(ec_dec_bit_logp(dec, 1))
+      {
+         int qg, octave;
+         octave = ec_dec_uint(dec, 6);
+         postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
+         qg = ec_dec_bits(dec, 3);
+         if (ec_tell(dec)+2<=total_bits)
+            postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
+         postfilter_gain = QCONST16(.09375f,15)*(qg+1);
+      }
+      tell = ec_tell(dec);
+   }
+
+   if (LM > 0 && tell+3 <= total_bits)
+   {
+      isTransient = ec_dec_bit_logp(dec, 3);
+      tell = ec_tell(dec);
+   }
+   else
+      isTransient = 0;
+
+   if (isTransient)
+      shortBlocks = M;
+   else
+      shortBlocks = 0;
+
+   /* Decode the global flags (first symbols in the stream) */
+   intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
+   /* If recovering from packet loss, make sure we make the energy prediction safe to reduce the
+      risk of getting loud artifacts. */
+   if (!intra_ener && st->loss_duration != 0) {
+      c=0; do
+      {
+         celt_glog safety = 0;
+         int missing = IMIN(10, st->loss_duration>>LM);
+         if (LM==0) safety = GCONST(1.5f);
+         else if (LM==1) safety = GCONST(.5f);
+         for (i=start;i<end;i++)
+         {
+            if (oldBandE[c*nbEBands+i] < MAXG(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) {
+               /* If energy is going down already, continue the trend. */
+               opus_val32 slope;
+               opus_val32 E0, E1, E2;
+               E0 = oldBandE[c*nbEBands+i];
+               E1 = oldLogE[c*nbEBands+i];
+               E2 = oldLogE2[c*nbEBands+i];
+               slope = MAX32(E1 - E0, HALF32(E2 - E0));
+               slope = MING(slope, GCONST(2.f));
+               E0 -= MAX32(0, (1+missing)*slope);
+               oldBandE[c*nbEBands+i] = MAX32(-GCONST(20.f), E0);
+            } else {
+               /* Otherwise take the min of the last frames. */
+               oldBandE[c*nbEBands+i] = MING(MING(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]);
+            }
+            /* Shorter frames have more natural fluctuations -- play it safe. */
+            oldBandE[c*nbEBands+i] -= safety;
+         }
+      } while (++c<2);
+   }
+   /* Get band energies */
+   unquant_coarse_energy(mode, start, end, oldBandE,
+         intra_ener, dec, C, LM);
+
+   ALLOC(tf_res, nbEBands, int);
+   tf_decode(start, end, isTransient, tf_res, LM, dec);
+
+   tell = ec_tell(dec);
+   spread_decision = SPREAD_NORMAL;
+   if (tell+4 <= total_bits)
+      spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
+
+   ALLOC(cap, nbEBands, int);
+
+   init_caps(mode,cap,LM,C);
+
+   ALLOC(offsets, nbEBands, int);
+
+   dynalloc_logp = 6;
+   total_bits<<=BITRES;
+   tell = ec_tell_frac(dec);
+   for (i=start;i<end;i++)
+   {
+      int width, quanta;
+      int dynalloc_loop_logp;
+      int boost;
+      width = C*(eBands[i+1]-eBands[i])<<LM;
+      /* quanta is 6 bits, but no more than 1 bit/sample
+         and no less than 1/8 bit/sample */
+      quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
+      dynalloc_loop_logp = dynalloc_logp;
+      boost = 0;
+      while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
+      {
+         int flag;
+         flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
+         tell = ec_tell_frac(dec);
+         if (!flag)
+            break;
+         boost += quanta;
+         total_bits -= quanta;
+         dynalloc_loop_logp = 1;
+      }
+      offsets[i] = boost;
+      /* Making dynalloc more likely */
+      if (boost>0)
+         dynalloc_logp = IMAX(2, dynalloc_logp-1);
+   }
+
+   ALLOC(fine_quant, nbEBands, int);
+   alloc_trim = tell+(6<<BITRES) <= total_bits ?
+         ec_dec_icdf(dec, trim_icdf, 7) : 5;
+
+   bits = (((opus_int32)len*8)<<BITRES) - (opus_int32)ec_tell_frac(dec) - 1;
+   anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
+   bits -= anti_collapse_rsv;
+
+   ALLOC(pulses, nbEBands, int);
+   ALLOC(fine_priority, nbEBands, int);
+
+   codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
+         alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
+         fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
+
+   unquant_fine_energy(mode, start, end, oldBandE, NULL, fine_quant, dec, C);
+
+   ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
+
+#ifdef ENABLE_QEXT
+   if (qext_bytes && end == nbEBands &&
+         ((mode->Fs == 48000 && (mode->shortMdctSize==120 || mode->shortMdctSize==90))
+       || (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)))) {
+      int qext_intra_ener;
+      compute_qext_mode(&qext_mode_struct, mode);
+      qext_mode = &qext_mode_struct;
+      qext_end = ec_dec_bit_logp(&ext_dec, 1) ? NB_QEXT_BANDS : 2;
+      if (C==2) decode_qext_stereo_params(&ext_dec, qext_end, &qext_intensity, &qext_dual_stereo);
+      qext_intra_ener = ec_tell(&ext_dec)+3<=qext_bytes*8 ? ec_dec_bit_logp(&ext_dec, 3) : 0;
+      unquant_coarse_energy(qext_mode, 0, qext_end, st->qext_oldBandE,
+            qext_intra_ener, &ext_dec, C, LM);
+   }
+   ALLOC(extra_quant, nbEBands+NB_QEXT_BANDS, int);
+   ALLOC(extra_pulses, nbEBands+NB_QEXT_BANDS, int);
+   qext_bits = ((opus_int32)qext_bytes*8<<BITRES) - (opus_int32)ec_tell_frac(dec) - 1;
+   clt_compute_extra_allocation(mode, qext_mode, start, end, qext_end, NULL, NULL,
+         qext_bits, extra_pulses, extra_quant, C, LM, &ext_dec, 0, 0, 0);
+   if (qext_bytes > 0) {
+      unquant_fine_energy(mode, start, end, oldBandE, fine_quant, extra_quant, &ext_dec, C);
+   }
+#endif
+
+   c=0; do {
+      OPUS_MOVE(decode_mem[c], decode_mem[c]+N, decode_buffer_size-N+overlap);
+   } while (++c<CC);
+
+   /* Decode fixed codebook */
+   ALLOC(collapse_masks, C*nbEBands, unsigned char);
+
+   quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
+         NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
+         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
+         st->arch, st->disable_inv
+         ARG_QEXT(&ext_dec) ARG_QEXT(extra_pulses)
+         ARG_QEXT(qext_bytes*(8<<BITRES)) ARG_QEXT(cap));
+
+#ifdef ENABLE_QEXT
+   if (qext_mode) {
+      VARDECL(int, zeros);
+      VARDECL(unsigned char, qext_collapse_masks);
+      ec_dec dummy_dec;
+      int ext_balance;
+      ALLOC(zeros, nbEBands, int);
+      ALLOC(qext_collapse_masks, C*NB_QEXT_BANDS, unsigned char);
+      ec_dec_init(&dummy_dec, NULL, 0);
+      OPUS_CLEAR(zeros, end);
+      ext_balance = qext_bytes*(8<<BITRES) - ec_tell_frac(&ext_dec);
+      for (i=0;i<qext_end;i++) ext_balance -= extra_pulses[nbEBands+i] + C*(extra_quant[nbEBands+1]<<BITRES);
+      unquant_fine_energy(qext_mode, 0, qext_end, st->qext_oldBandE, NULL, &extra_quant[nbEBands], &ext_dec, C);
+      quant_all_bands(0, qext_mode, 0, qext_end, X, C==2 ? X+N : NULL, qext_collapse_masks,
+            NULL, &extra_pulses[nbEBands], shortBlocks, spread_decision, qext_dual_stereo, qext_intensity, zeros,
+            qext_bytes*(8<<BITRES), ext_balance, &ext_dec, LM, qext_end, &st->rng, 0,
+            st->arch, st->disable_inv, &dummy_dec, zeros, 0, NULL);
+   }
+#endif
+
+   if (anti_collapse_rsv > 0)
+   {
+      anti_collapse_on = ec_dec_bits(dec, 1);
+   }
+   unquant_energy_finalise(mode, start, end, (qext_bytes > 0) ? NULL : oldBandE,
+         fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
+   if (anti_collapse_on)
+      anti_collapse(mode, X, collapse_masks, LM, C, N,
+            start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, 0, st->arch);
+
+   if (silence)
+   {
+      for (i=0;i<C*nbEBands;i++)
+         oldBandE[i] = -GCONST(28.f);
+   }
+   if (st->prefilter_and_fold) {
+      prefilter_and_fold(st, N);
+   }
+   celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
+                  C, CC, isTransient, LM, st->downsample, silence, st->arch ARG_QEXT(qext_mode) ARG_QEXT(st->qext_oldBandE) ARG_QEXT(qext_end));
+
+   c=0; do {
+      st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
+      st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
+      comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
+            st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
+            mode->window, overlap, st->arch);
+      if (LM!=0)
+         comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
+               st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
+               mode->window, overlap, st->arch);
+
+   } while (++c<CC);
+   st->postfilter_period_old = st->postfilter_period;
+   st->postfilter_gain_old = st->postfilter_gain;
+   st->postfilter_tapset_old = st->postfilter_tapset;
+   st->postfilter_period = postfilter_pitch;
+   st->postfilter_gain = postfilter_gain;
+   st->postfilter_tapset = postfilter_tapset;
+   if (LM!=0)
+   {
+      st->postfilter_period_old = st->postfilter_period;
+      st->postfilter_gain_old = st->postfilter_gain;
+      st->postfilter_tapset_old = st->postfilter_tapset;
+   }
+
+   if (C==1)
+      OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
+
+   if (!isTransient)
+   {
+      OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
+      OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
+   } else {
+      for (i=0;i<2*nbEBands;i++)
+         oldLogE[i] = MING(oldLogE[i], oldBandE[i]);
+   }
+   /* In normal circumstances, we only allow the noise floor to increase by
+      up to 2.4 dB/second, but when we're in DTX we give the weight of
+      all missing packets to the update packet. */
+   max_background_increase = IMIN(160, st->loss_duration+M)*GCONST(0.001f);
+   for (i=0;i<2*nbEBands;i++)
+      backgroundLogE[i] = MING(backgroundLogE[i] + max_background_increase, oldBandE[i]);
+   /* In case start or end were to change */
+   c=0; do
+   {
+      for (i=0;i<start;i++)
+      {
+         oldBandE[c*nbEBands+i]=0;
+         oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
+      }
+      for (i=end;i<nbEBands;i++)
+      {
+         oldBandE[c*nbEBands+i]=0;
+         oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
+      }
+   } while (++c<2);
+   st->rng = dec->rng;
+#ifdef ENABLE_QEXT
+   if (qext_bytes) st->rng = st->rng ^ ext_dec.rng;
+#endif
+
+   deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
+   st->loss_duration = 0;
+   st->plc_duration = 0;
+   st->last_frame_type = FRAME_NORMAL;
+   st->prefilter_and_fold = 0;
+   RESTORE_STACK;
+   if (ec_tell(dec) > 8*len)
+      return OPUS_INTERNAL_ERROR;
+#ifdef ENABLE_QEXT
+   if (qext_bytes != 0 && ec_tell(&ext_dec) > 8*qext_bytes)
+      return OPUS_INTERNAL_ERROR;
+#endif
+   if(ec_get_error(dec))
+      st->error = 1;
+   return frame_size/st->downsample;
+}
+
+int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+      int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
+{
+   return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum
+#ifdef ENABLE_DEEP_PLC
+       , NULL
+#endif
+       ARG_QEXT(NULL) ARG_QEXT(0)
+       );
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+
+#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
+{
+   return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+#else
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
+{
+   int j, ret, C, N;
+   VARDECL(opus_res, out);
+   ALLOC_STACK;
+
+   if (pcm==NULL)
+      return OPUS_BAD_ARG;
+
+   C = st->channels;
+   N = frame_size;
+
+   ALLOC(out, C*N, opus_res);
+   ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+   if (ret>0)
+      for (j=0;j<C*ret;j++)
+         pcm[j]=RES2INT16(out[j]);
+
+   RESTORE_STACK;
+   return ret;
+}
+#endif
+
+#if defined(FIXED_POINT) && defined(ENABLE_RES24)
+int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
+{
+   return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+#else
+int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
+{
+   int j, ret, C, N;
+   VARDECL(opus_res, out);
+   ALLOC_STACK;
+
+   if (pcm==NULL)
+      return OPUS_BAD_ARG;
+
+   C = st->channels;
+   N = frame_size;
+
+   ALLOC(out, C*N, opus_res);
+   ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+   if (ret>0)
+      for (j=0;j<C*ret;j++)
+         pcm[j]=RES2INT24(out[j]);
+
+   RESTORE_STACK;
+   return ret;
+}
+#endif
+
+
+#ifndef DISABLE_FLOAT_API
+
+# if !defined(FIXED_POINT)
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
+{
+   return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+# else
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
+{
+   int j, ret, C, N;
+   VARDECL(opus_res, out);
+   ALLOC_STACK;
+
+   if (pcm==NULL)
+      return OPUS_BAD_ARG;
+
+   C = st->channels;
+   N = frame_size;
+
+   ALLOC(out, C*N, opus_res);
+   ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+   if (ret>0)
+      for (j=0;j<C*ret;j++)
+         pcm[j]=RES2FLOAT(out[j]);
+
+   RESTORE_STACK;
+   return ret;
+}
+# endif
+
+#endif
+
+#endif /* CUSTOM_MODES */
+
+int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
+{
+   va_list ap;
+
+   va_start(ap, request);
+   switch (request)
+   {
+      case OPUS_SET_COMPLEXITY_REQUEST:
+      {
+          opus_int32 value = va_arg(ap, opus_int32);
+          if(value<0 || value>10)
+          {
+             goto bad_arg;
+          }
+          st->complexity = value;
+      }
+      break;
+      case OPUS_GET_COMPLEXITY_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->complexity;
+      }
+      break;
+      case CELT_SET_START_BAND_REQUEST:
+      {
+         opus_int32 value = va_arg(ap, opus_int32);
+         if (value<0 || value>=st->mode->nbEBands)
+            goto bad_arg;
+         st->start = value;
+      }
+      break;
+      case CELT_SET_END_BAND_REQUEST:
+      {
+         opus_int32 value = va_arg(ap, opus_int32);
+         if (value<1 || value>st->mode->nbEBands)
+            goto bad_arg;
+         st->end = value;
+      }
+      break;
+      case CELT_SET_CHANNELS_REQUEST:
+      {
+         opus_int32 value = va_arg(ap, opus_int32);
+         if (value<1 || value>2)
+            goto bad_arg;
+         st->stream_channels = value;
+      }
+      break;
+      case CELT_GET_AND_CLEAR_ERROR_REQUEST:
+      {
+         opus_int32 *value = va_arg(ap, opus_int32*);
+         if (value==NULL)
+            goto bad_arg;
+         *value=st->error;
+         st->error = 0;
+      }
+      break;
+      case OPUS_GET_LOOKAHEAD_REQUEST:
+      {
+         opus_int32 *value = va_arg(ap, opus_int32*);
+         if (value==NULL)
+            goto bad_arg;
+         *value = st->overlap/st->downsample;
+      }
+      break;
+      case OPUS_RESET_STATE:
+      {
+         int i;
+         celt_glog *oldBandE, *oldLogE, *oldLogE2;
+         int decode_buffer_size;
+#ifdef ENABLE_QEXT
+         int qext_scale = st->qext_scale;
+#endif
+         decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+         oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+st->overlap)*st->channels);
+         oldLogE = oldBandE + 2*st->mode->nbEBands;
+         oldLogE2 = oldLogE + 2*st->mode->nbEBands;
+         OPUS_CLEAR((char*)&st->DECODER_RESET_START,
+               opus_custom_decoder_get_size(st->mode, st->channels)-
+               ((char*)&st->DECODER_RESET_START - (char*)st));
+         for (i=0;i<2*st->mode->nbEBands;i++)
+            oldLogE[i]=oldLogE2[i]=-GCONST(28.f);
+         st->skip_plc = 1;
+         st->last_frame_type = FRAME_NONE;
+      }
+      break;
+      case OPUS_GET_PITCH_REQUEST:
+      {
+         opus_int32 *value = va_arg(ap, opus_int32*);
+         if (value==NULL)
+            goto bad_arg;
+         *value = st->postfilter_period;
+      }
+      break;
+      case CELT_GET_MODE_REQUEST:
+      {
+         const CELTMode ** value = va_arg(ap, const CELTMode**);
+         if (value==0)
+            goto bad_arg;
+         *value=st->mode;
+      }
+      break;
+      case CELT_SET_SIGNALLING_REQUEST:
+      {
+         opus_int32 value = va_arg(ap, opus_int32);
+         st->signalling = value;
+      }
+      break;
+      case OPUS_GET_FINAL_RANGE_REQUEST:
+      {
+         opus_uint32 * value = va_arg(ap, opus_uint32 *);
+         if (value==0)
+            goto bad_arg;
+         *value=st->rng;
+      }
+      break;
+      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 value = va_arg(ap, opus_int32);
+          if(value<0 || value>1)
+          {
+             goto bad_arg;
+          }
+          st->disable_inv = value;
+      }
+      break;
+      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->disable_inv;
+      }
+      break;
+      default:
+         goto bad_request;
+   }
+   va_end(ap);
+   return OPUS_OK;
+bad_arg:
+   va_end(ap);
+   return OPUS_BAD_ARG;
+bad_request:
+      va_end(ap);
+  return OPUS_UNIMPLEMENTED;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.c
new file mode 100644 (file)
index 0000000..e5a1c48
--- /dev/null
@@ -0,0 +1,374 @@
+/* Copyright (c) 2009-2010 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+void _celt_lpc(
+      opus_val16       *_lpc, /* out: [0...p-1] LPC coefficients      */
+const opus_val32 *ac,  /* in:  [0...p] autocorrelation values  */
+int          p
+)
+{
+   int i, j;
+   opus_val32 r;
+   opus_val32 error = ac[0];
+#ifdef FIXED_POINT
+   opus_val32 lpc[CELT_LPC_ORDER];
+#else
+   float *lpc = _lpc;
+#endif
+
+   OPUS_CLEAR(lpc, p);
+#ifdef FIXED_POINT
+   if (ac[0] != 0)
+#else
+   if (ac[0] > 1e-10f)
+#endif
+   {
+      for (i = 0; i < p; i++) {
+         /* Sum up this iteration's reflection coefficient */
+         opus_val32 rr = 0;
+#if defined (FIXED_POINT) && OPUS_FAST_INT64
+         opus_int64 acc = 0;
+         for (j = 0; j < i; j++)
+            acc += (opus_int64)(lpc[j]) * (opus_int64)(ac[i - j]);
+         rr = (opus_val32)SHR64(acc, 31);
+#else
+         for (j = 0; j < i; j++)
+            rr += MULT32_32_Q31(lpc[j],ac[i - j]);
+#endif
+         rr += SHR32(ac[i + 1],6);
+         r = -frac_div32(SHL32(rr,6), error);
+         /*  Update LPC coefficients and total error */
+         lpc[i] = SHR32(r,6);
+         for (j = 0; j < (i+1)>>1; j++)
+         {
+            opus_val32 tmp1, tmp2;
+            tmp1 = lpc[j];
+            tmp2 = lpc[i-1-j];
+            lpc[j]     = tmp1 + MULT32_32_Q31(r,tmp2);
+            lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
+         }
+
+         error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
+         /* Bail out once we get 30 dB gain */
+#ifdef FIXED_POINT
+         if (error<=SHR32(ac[0],10))
+            break;
+#else
+         if (error<=.001f*ac[0])
+            break;
+#endif
+      }
+   }
+#ifdef FIXED_POINT
+   {
+      /* Convert the int32 lpcs to int16 and ensure there are no wrap-arounds.
+         This reuses the logic in silk_LPC_fit() and silk_bwexpander_32(). Any bug
+         fixes should also be applied there. */
+      int iter, idx = 0;
+      opus_val32 maxabs, absval, chirp_Q16, chirp_minus_one_Q16;
+
+      for (iter = 0; iter < 10; iter++) {
+         maxabs = 0;
+         for (i = 0; i < p; i++) {
+            absval = ABS32(lpc[i]);
+            if (absval > maxabs) {
+               maxabs = absval;
+               idx = i;
+            }
+         }
+         maxabs = PSHR32(maxabs, 13);  /* Q25->Q12 */
+
+         if (maxabs > 32767) {
+            maxabs = MIN32(maxabs, 163838);
+            chirp_Q16 = QCONST32(0.999, 16) - DIV32(SHL32(maxabs - 32767, 14),
+                                                    SHR32(MULT32_32_32(maxabs, idx + 1), 2));
+            chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+            /* Apply bandwidth expansion. */
+            for (i = 0; i < p - 1; i++) {
+               lpc[i] = MULT32_32_Q16(chirp_Q16, lpc[i]);
+               chirp_Q16 += PSHR32(MULT32_32_32(chirp_Q16, chirp_minus_one_Q16), 16);
+            }
+            lpc[p - 1] = MULT32_32_Q16(chirp_Q16, lpc[p - 1]);
+         } else {
+            break;
+         }
+      }
+
+      if (iter == 10) {
+         /* If the coeffs still do not fit into the 16 bit range after 10 iterations,
+            fall back to the A(z)=1 filter. */
+         OPUS_CLEAR(lpc, p);
+         _lpc[0] = 4096;  /* Q12 */
+      } else {
+         for (i = 0; i < p; i++) {
+            _lpc[i] = EXTRACT16(PSHR32(lpc[i], 13));  /* Q25->Q12 */
+         }
+      }
+   }
+#endif
+}
+
+
+void celt_fir_c(
+         const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16 *y,
+         int N,
+         int ord,
+         int arch)
+{
+   int i,j;
+   VARDECL(opus_val16, rnum);
+   SAVE_STACK;
+   celt_assert(x != y);
+   ALLOC(rnum, ord, opus_val16);
+   for(i=0;i<ord;i++)
+      rnum[i] = num[ord-i-1];
+   for (i=0;i<N-3;i+=4)
+   {
+      opus_val32 sum[4];
+      sum[0] = SHL32(EXTEND32(x[i  ]), SIG_SHIFT);
+      sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
+      sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
+      sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+      {
+         opus_val32 sum_c[4];
+         memcpy(sum_c, sum, sizeof(sum_c));
+         xcorr_kernel_c(rnum, x+i-ord, sum_c, ord);
+#endif
+         xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+      }
+#endif
+      y[i  ] = SROUND16(sum[0], SIG_SHIFT);
+      y[i+1] = SROUND16(sum[1], SIG_SHIFT);
+      y[i+2] = SROUND16(sum[2], SIG_SHIFT);
+      y[i+3] = SROUND16(sum[3], SIG_SHIFT);
+   }
+   for (;i<N;i++)
+   {
+      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
+      for (j=0;j<ord;j++)
+         sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
+      y[i] = SROUND16(sum, SIG_SHIFT);
+   }
+   RESTORE_STACK;
+}
+
+void celt_iir(const opus_val32 *_x,
+         const opus_val16 *den,
+         opus_val32 *_y,
+         int N,
+         int ord,
+         opus_val16 *mem,
+         int arch)
+{
+#ifdef SMALL_FOOTPRINT
+   int i,j;
+   (void)arch;
+   for (i=0;i<N;i++)
+   {
+      opus_val32 sum = _x[i];
+      for (j=0;j<ord;j++)
+      {
+         sum -= MULT16_16(den[j],mem[j]);
+      }
+      for (j=ord-1;j>=1;j--)
+      {
+         mem[j]=mem[j-1];
+      }
+      mem[0] = SROUND16(sum, SIG_SHIFT);
+      _y[i] = sum;
+   }
+#else
+   int i,j;
+   VARDECL(opus_val16, rden);
+   VARDECL(opus_val16, y);
+   SAVE_STACK;
+
+   celt_assert((ord&3)==0);
+   ALLOC(rden, ord, opus_val16);
+   ALLOC(y, N+ord, opus_val16);
+   for(i=0;i<ord;i++)
+      rden[i] = den[ord-i-1];
+   for(i=0;i<ord;i++)
+      y[i] = -mem[ord-i-1];
+   for(;i<N+ord;i++)
+      y[i]=0;
+   for (i=0;i<N-3;i+=4)
+   {
+      /* Unroll by 4 as if it were an FIR filter */
+      opus_val32 sum[4];
+      sum[0]=_x[i];
+      sum[1]=_x[i+1];
+      sum[2]=_x[i+2];
+      sum[3]=_x[i+3];
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+      {
+         opus_val32 sum_c[4];
+         memcpy(sum_c, sum, sizeof(sum_c));
+         xcorr_kernel_c(rden, y+i, sum_c, ord);
+#endif
+         xcorr_kernel(rden, y+i, sum, ord, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+      }
+#endif
+      /* Patch up the result to compensate for the fact that this is an IIR */
+      y[i+ord  ] = -SROUND16(sum[0],SIG_SHIFT);
+      _y[i  ] = sum[0];
+      sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
+      y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
+      _y[i+1] = sum[1];
+      sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
+      sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
+      y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
+      _y[i+2] = sum[2];
+
+      sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
+      sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
+      sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
+      y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
+      _y[i+3] = sum[3];
+   }
+   for (;i<N;i++)
+   {
+      opus_val32 sum = _x[i];
+      for (j=0;j<ord;j++)
+         sum -= MULT16_16(rden[j],y[i+j]);
+      y[i+ord] = SROUND16(sum,SIG_SHIFT);
+      _y[i] = sum;
+   }
+   for(i=0;i<ord;i++)
+      mem[i] = _y[N-i-1];
+   RESTORE_STACK;
+#endif
+}
+
+int _celt_autocorr(
+                   const opus_val16 *x,   /*  in: [0...n-1] samples x   */
+                   opus_val32       *ac,  /* out: [0...lag-1] ac values */
+                   const celt_coef  *window,
+                   int          overlap,
+                   int          lag,
+                   int          n,
+                   int          arch
+                  )
+{
+   opus_val32 d;
+   int i, k;
+   int fastN=n-lag;
+   int shift;
+   const opus_val16 *xptr;
+   VARDECL(opus_val16, xx);
+   SAVE_STACK;
+   ALLOC(xx, n, opus_val16);
+   celt_assert(n>0);
+   celt_assert(overlap>=0);
+   if (overlap == 0)
+   {
+      xptr = x;
+   } else {
+      for (i=0;i<n;i++)
+         xx[i] = x[i];
+      for (i=0;i<overlap;i++)
+      {
+         opus_val16 w = COEF2VAL16(window[i]);
+         xx[i] = MULT16_16_Q15(x[i],w);
+         xx[n-i-1] = MULT16_16_Q15(x[n-i-1],w);
+      }
+      xptr = xx;
+   }
+   shift=0;
+#ifdef FIXED_POINT
+   {
+      opus_val32 ac0;
+      int ac0_shift = celt_ilog2(n + (n>>4));
+      ac0 = 1+(n<<7);
+      if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),ac0_shift);
+      for(i=(n&1);i<n;i+=2)
+      {
+         ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),ac0_shift);
+         ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),ac0_shift);
+      }
+      /* Consider the effect of rounding-to-nearest when scaling the signal. */
+      ac0 += SHR32(ac0,7);
+
+      shift = celt_ilog2(ac0)-30+ac0_shift+1;
+      shift = (shift)/2;
+      if (shift>0)
+      {
+         for(i=0;i<n;i++)
+            xx[i] = PSHR32(xptr[i], shift);
+         xptr = xx;
+      } else
+         shift = 0;
+   }
+#endif
+   celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
+   for (k=0;k<=lag;k++)
+   {
+      for (i = k+fastN, d = 0; i < n; i++)
+         d = MAC16_16(d, xptr[i], xptr[i-k]);
+      ac[k] += d;
+   }
+#ifdef FIXED_POINT
+   shift = 2*shift;
+   if (shift<=0)
+      ac[0] += SHL32((opus_int32)1, -shift);
+   if (ac[0] < 268435456)
+   {
+      int shift2 = 29 - EC_ILOG(ac[0]);
+      for (i=0;i<=lag;i++)
+         ac[i] = SHL32(ac[i], shift2);
+      shift -= shift2;
+   } else if (ac[0] >= 536870912)
+   {
+      int shift2=1;
+      if (ac[0] >= 1073741824)
+         shift2++;
+      for (i=0;i<=lag;i++)
+         ac[i] = SHR32(ac[i], shift2);
+      shift += shift2;
+   }
+#endif
+
+   RESTORE_STACK;
+   return shift;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/celt_lpc.h
new file mode 100644 (file)
index 0000000..e710946
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (c) 2009-2010 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CELT_LPC_H
+#define CELT_LPC_H
+
+#include "arch.h"
+#include "cpu_support.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/celt_lpc_sse.h"
+#endif
+
+#define CELT_LPC_ORDER 24
+
+void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
+
+void celt_fir_c(
+         const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16 *y,
+         int N,
+         int ord,
+         int arch);
+
+#if !defined(OVERRIDE_CELT_FIR)
+#define celt_fir(x, num, y, N, ord, arch) \
+    (celt_fir_c(x, num, y, N, ord, arch))
+#endif
+
+void celt_iir(const opus_val32 *x,
+         const opus_val16 *den,
+         opus_val32 *y,
+         int N,
+         int ord,
+         opus_val16 *mem,
+         int arch);
+
+int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
+         const celt_coef *window, int overlap, int lag, int n, int arch);
+
+#endif /* CELT_LPC_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cpu_support.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cpu_support.h
new file mode 100644 (file)
index 0000000..9f13d8a
--- /dev/null
@@ -0,0 +1,72 @@
+/* Copyright (c) 2010 Xiph.Org Foundation
+ * Copyright (c) 2013 Parrot */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CPU_SUPPORT_H
+#define CPU_SUPPORT_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if defined(OPUS_HAVE_RTCD) && \
+  (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/armcpu.h"
+
+/* We currently support 5 ARM variants:
+ * arch[0] -> ARMv4
+ * arch[1] -> ARMv5E
+ * arch[2] -> ARMv6
+ * arch[3] -> NEON
+ * arch[4] -> NEON+DOTPROD
+ */
+#define OPUS_ARCHMASK 7
+
+#elif defined(OPUS_HAVE_RTCD) && \
+  ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+  (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+
+#include "x86/x86cpu.h"
+/* We currently support 5 x86 variants:
+ * arch[0] -> non-sse
+ * arch[1] -> sse
+ * arch[2] -> sse2
+ * arch[3] -> sse4.1
+ * arch[4] -> avx
+ */
+#define OPUS_ARCHMASK 7
+int opus_select_arch(void);
+
+#else
+#define OPUS_ARCHMASK 0
+
+static OPUS_INLINE int opus_select_arch(void)
+{
+  return 0;
+}
+#endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.c
new file mode 100644 (file)
index 0000000..8a280ce
--- /dev/null
@@ -0,0 +1,719 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2007-2009 Timothy B. Terriberry
+   Written by Timothy B. Terriberry and Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "os_support.h"
+#include "cwrs.h"
+#include "mathops.h"
+#include "arch.h"
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_QEXT)
+#define CWRS_EXTRA_ROWS
+#endif
+
+#if defined(CUSTOM_MODES)
+
+/*Guaranteed to return a conservatively large estimate of the binary logarithm
+   with frac bits of fractional precision.
+  Tested for all possible 32-bit inputs with frac=4, where the maximum
+   overestimation is 0.06254243 bits.*/
+int log2_frac(opus_uint32 val, int frac)
+{
+  int l;
+  l=EC_ILOG(val);
+  if(val&(val-1)){
+    /*This is (val>>l-16), but guaranteed to round up, even if adding a bias
+       before the shift would cause overflow (e.g., for 0xFFFFxxxx).
+       Doesn't work for val=0, but that case fails the test above.*/
+    if(l>16)val=((val-1)>>(l-16))+1;
+    else val<<=16-l;
+    l=(l-1)<<frac;
+    /*Note that we always need one iteration, since the rounding up above means
+       that we might need to adjust the integer part of the logarithm.*/
+    do{
+      int b;
+      b=(int)(val>>16);
+      l+=b<<frac;
+      val=(val+b)>>b;
+      val=(val*val+0x7FFF)>>15;
+    }
+    while(frac-->0);
+    /*If val is not exactly 0x8000, then we have to round up the remainder.*/
+    return l+(val>0x8000);
+  }
+  /*Exact powers of two require no rounding.*/
+  else return (l-1)<<frac;
+}
+#endif
+
+/*Although derived separately, the pulse vector coding scheme is equivalent to
+   a Pyramid Vector Quantizer \cite{Fis86}.
+  Some additional notes about an early version appear at
+   https://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
+   and the definitions of some terms have evolved since that was written.
+
+  The conversion from a pulse vector to an integer index (encoding) and back
+   (decoding) is governed by two related functions, V(N,K) and U(N,K).
+
+  V(N,K) = the number of combinations, with replacement, of N items, taken K
+   at a time, when a sign bit is added to each item taken at least once (i.e.,
+   the number of N-dimensional unit pulse vectors with K pulses).
+  One way to compute this is via
+    V(N,K) = K>0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1,
+   where choose() is the binomial function.
+  A table of values for N<10 and K<10 looks like:
+  V[10][10] = {
+    {1,  0,   0,    0,    0,     0,     0,      0,      0,       0},
+    {1,  2,   2,    2,    2,     2,     2,      2,      2,       2},
+    {1,  4,   8,   12,   16,    20,    24,     28,     32,      36},
+    {1,  6,  18,   38,   66,   102,   146,    198,    258,     326},
+    {1,  8,  32,   88,  192,   360,   608,    952,   1408,    1992},
+    {1, 10,  50,  170,  450,  1002,  1970,   3530,   5890,    9290},
+    {1, 12,  72,  292,  912,  2364,  5336,  10836,  20256,   35436},
+    {1, 14,  98,  462, 1666,  4942, 12642,  28814,  59906,  115598},
+    {1, 16, 128,  688, 2816,  9424, 27008,  68464, 157184,  332688},
+    {1, 18, 162,  978, 4482, 16722, 53154, 148626, 374274,  864146}
+  };
+
+  U(N,K) = the number of such combinations wherein N-1 objects are taken at
+   most K-1 at a time.
+  This is given by
+    U(N,K) = sum(k=0...K-1,V(N-1,k))
+           = K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0.
+  The latter expression also makes clear that U(N,K) is half the number of such
+   combinations wherein the first object is taken at least once.
+  Although it may not be clear from either of these definitions, U(N,K) is the
+   natural function to work with when enumerating the pulse vector codebooks,
+   not V(N,K).
+  U(N,K) is not well-defined for N=0, but with the extension
+    U(0,K) = K>0 ? 0 : 1,
+   the function becomes symmetric: U(N,K) = U(K,N), with a similar table:
+  U[10][10] = {
+    {1, 0,  0,   0,    0,    0,     0,     0,      0,      0},
+    {0, 1,  1,   1,    1,    1,     1,     1,      1,      1},
+    {0, 1,  3,   5,    7,    9,    11,    13,     15,     17},
+    {0, 1,  5,  13,   25,   41,    61,    85,    113,    145},
+    {0, 1,  7,  25,   63,  129,   231,   377,    575,    833},
+    {0, 1,  9,  41,  129,  321,   681,  1289,   2241,   3649},
+    {0, 1, 11,  61,  231,  681,  1683,  3653,   7183,  13073},
+    {0, 1, 13,  85,  377, 1289,  3653,  8989,  19825,  40081},
+    {0, 1, 15, 113,  575, 2241,  7183, 19825,  48639, 108545},
+    {0, 1, 17, 145,  833, 3649, 13073, 40081, 108545, 265729}
+  };
+
+  With this extension, V(N,K) may be written in terms of U(N,K):
+    V(N,K) = U(N,K) + U(N,K+1)
+   for all N>=0, K>=0.
+  Thus U(N,K+1) represents the number of combinations where the first element
+   is positive or zero, and U(N,K) represents the number of combinations where
+   it is negative.
+  With a large enough table of U(N,K) values, we could write O(N) encoding
+   and O(min(N*log(K),N+K)) decoding routines, but such a table would be
+   prohibitively large for small embedded devices (K may be as large as 32767
+   for small N, and N may be as large as 200).
+
+  Both functions obey the same recurrence relation:
+    V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1),
+    U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1),
+   for all N>0, K>0, with different initial conditions at N=0 or K=0.
+  This allows us to construct a row of one of the tables above given the
+   previous row or the next row.
+  Thus we can derive O(NK) encoding and decoding routines with O(K) memory
+   using only addition and subtraction.
+
+  When encoding, we build up from the U(2,K) row and work our way forwards.
+  When decoding, we need to start at the U(N,K) row and work our way backwards,
+   which requires a means of computing U(N,K).
+  U(N,K) may be computed from two previous values with the same N:
+    U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2)
+   for all N>1, and since U(N,K) is symmetric, a similar relation holds for two
+   previous values with the same K:
+    U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K)
+   for all K>1.
+  This allows us to construct an arbitrary row of the U(N,K) table by starting
+   with the first two values, which are constants.
+  This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K)
+   multiplications.
+  Similar relations can be derived for V(N,K), but are not used here.
+
+  For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree
+   polynomial for fixed N.
+  The first few are
+    U(1,K) = 1,
+    U(2,K) = 2*K-1,
+    U(3,K) = (2*K-2)*K+1,
+    U(4,K) = (((4*K-6)*K+8)*K-3)/3,
+    U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3,
+   and
+    V(1,K) = 2,
+    V(2,K) = 4*K,
+    V(3,K) = 4*K*K+2,
+    V(4,K) = 8*(K*K+2)*K/3,
+    V(5,K) = ((4*K*K+20)*K*K+6)/3,
+   for all K>0.
+  This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for
+   small N (and indeed decoding is also O(N) for N<3).
+
+  @ARTICLE{Fis86,
+    author="Thomas R. Fischer",
+    title="A Pyramid Vector Quantizer",
+    journal="IEEE Transactions on Information Theory",
+    volume="IT-32",
+    number=4,
+    pages="568--583",
+    month=Jul,
+    year=1986
+  }*/
+
+#if !defined(SMALL_FOOTPRINT)
+
+/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/
+# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)])
+/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N
+   with K pulses allocated to it.*/
+# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1))
+
+/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)).
+  Thus, the number of entries in row I is the larger of the maximum number of
+   pulses we will ever allocate for a given N=I (K=128, or however many fit in
+   32 bits, whichever is smaller), plus one, and the maximum N for which
+   K=I-1 pulses fit in 32 bits.
+  The largest band size in an Opus Custom mode is 208.
+  Otherwise, we can limit things to the set of N which can be achieved by
+   splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48,
+   44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/
+#if defined(CWRS_EXTRA_ROWS)
+static const opus_uint32 CELT_PVQ_U_DATA[1488]={
+#else
+static const opus_uint32 CELT_PVQ_U_DATA[1272]={
+#endif
+  /*N=0, K=0...176:*/
+  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0,
+#endif
+  /*N=1, K=1...176:*/
+  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, 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, 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,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1,
+#endif
+  /*N=2, K=2...176:*/
+  3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
+  43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79,
+  81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113,
+  115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143,
+  145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
+  175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203,
+  205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233,
+  235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263,
+  265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293,
+  295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323,
+  325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381,
+  383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411,
+  413, 415,
+#endif
+  /*N=3, K=3...176:*/
+  13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613,
+  685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861,
+  1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785,
+  3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385,
+  6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661,
+  9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961,
+  13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745,
+  17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013,
+  21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765,
+  26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001,
+  31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721,
+  37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925,
+  43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613,
+  50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785,
+  57461, 58141, 58825, 59513, 60205, 60901, 61601,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565,
+  70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013,
+  78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113,
+#endif
+  /*N=4, K=4...176:*/
+  63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017,
+  7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775,
+  30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153,
+  82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193,
+  161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575,
+  267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217,
+  410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951,
+  597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609,
+  833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023,
+  1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407,
+  1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759,
+  1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175,
+  2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751,
+  2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583,
+  3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767,
+  3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399,
+  4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575,
+  5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391,
+  6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943,
+  7085049, 7207551,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783,
+  8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967,
+  9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199,
+  10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177,
+  11912575,
+#endif
+  /*N=5, K=5...176:*/
+  321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041,
+  50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401,
+  330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241,
+  1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241,
+  2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801,
+  4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849,
+  8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849,
+  13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809,
+  20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881,
+  29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641,
+  40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081,
+  55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609,
+  73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049,
+  95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641,
+  122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041,
+  155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321,
+  193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969,
+  238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889,
+  290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401,
+  351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241,
+  420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561,
+  500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929,
+  590359041, 604167209, 618216201, 632508801,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...208:*/
+  647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241,
+  755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161,
+  878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329,
+  1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041,
+  1143412929, 1166053121, 1189027881, 1212340489, 1235994241,
+#endif
+  /*N=6, K=6...96:*/
+  1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047,
+  335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409,
+  2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793,
+  11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455,
+  29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189,
+  64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651,
+  128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185,
+  235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647,
+  402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229,
+  655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283,
+  1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135,
+  1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187,
+  2011371957, 2120032959,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...109:*/
+  2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U,
+  3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U,
+  4012305913U,
+#endif
+  /*N=7, K=7...54*/
+  8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777,
+  1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233,
+  19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013,
+  88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805,
+  292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433,
+  793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821,
+  1667010073, 1870535785, 2094367717,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...60:*/
+  2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U,
+#endif
+  /*N=8, K=8...37*/
+  48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767,
+  9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017,
+  104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351,
+  638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615,
+  2229491905U,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...40:*/
+  2691463695U, 3233240945U, 3866006015U,
+#endif
+  /*N=9, K=9...28:*/
+  265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777,
+  39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145,
+  628496897, 872893441, 1196924561, 1621925137, 2173806145U,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...29:*/
+  2883810113U,
+#endif
+  /*N=10, K=10...24:*/
+  1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073,
+  254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U,
+  3375210671U,
+  /*N=11, K=11...19:*/
+  8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585,
+  948062325, 1616336765,
+#if defined(CWRS_EXTRA_ROWS)
+  /*...20:*/
+  2684641785U,
+#endif
+  /*N=12, K=12...18:*/
+  45046719, 103274625, 224298231, 464387817, 921406335, 1759885185,
+  3248227095U,
+  /*N=13, K=13...16:*/
+  251595969, 579168825, 1267854873, 2653649025U,
+  /*N=14, K=14:*/
+  1409933619
+};
+
+#if defined(CWRS_EXTRA_ROWS)
+static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
+  CELT_PVQ_U_DATA+   0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415,
+  CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030,
+  CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389,
+  CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455,
+  CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473
+};
+#else
+static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
+  CELT_PVQ_U_DATA+   0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351,
+  CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870,
+  CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178,
+  CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240,
+  CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257
+};
+#endif
+
+#if defined(CUSTOM_MODES)
+void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
+  int k;
+  /*_maxk==0 => there's nothing to do.*/
+  celt_assert(_maxk>0);
+  _bits[0]=0;
+  for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac);
+}
+#endif
+
+static opus_uint32 icwrs(int _n,const int *_y){
+  opus_uint32 i;
+  int         j;
+  int         k;
+  celt_assert(_n>=2);
+  j=_n-1;
+  i=_y[j]<0;
+  k=abs(_y[j]);
+  do{
+    j--;
+    i+=CELT_PVQ_U(_n-j,k);
+    k+=abs(_y[j]);
+    if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1);
+  }
+  while(j>0);
+  return i;
+}
+
+void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
+  celt_assert(_k>0);
+  ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k));
+}
+
+static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
+  opus_uint32 p;
+  int         s;
+  int         k0;
+  opus_int16  val;
+  opus_val32  yy=0;
+  celt_assert(_k>0);
+  celt_assert(_n>1);
+  while(_n>2){
+    opus_uint32 q;
+    /*Lots of pulses case:*/
+    if(_k>=_n){
+      const opus_uint32 *row;
+      row=CELT_PVQ_U_ROW[_n];
+      /*Are the pulses in this dimension negative?*/
+      p=row[_k+1];
+      s=-(_i>=p);
+      _i-=p&s;
+      /*Count how many pulses were placed in this dimension.*/
+      k0=_k;
+      q=row[_n];
+      if(q>_i){
+        celt_sig_assert(p>q);
+        _k=_n;
+        do p=CELT_PVQ_U_ROW[--_k][_n];
+        while(p>_i);
+      }
+      else for(p=row[_k];p>_i;p=row[_k])_k--;
+      _i-=p;
+      val=(k0-_k+s)^s;
+      *_y++=val;
+      yy=MAC16_16(yy,val,val);
+    }
+    /*Lots of dimensions case:*/
+    else{
+      /*Are there any pulses in this dimension at all?*/
+      p=CELT_PVQ_U_ROW[_k][_n];
+      q=CELT_PVQ_U_ROW[_k+1][_n];
+      if(p<=_i&&_i<q){
+        _i-=p;
+        *_y++=0;
+      }
+      else{
+        /*Are the pulses in this dimension negative?*/
+        s=-(_i>=q);
+        _i-=q&s;
+        /*Count how many pulses were placed in this dimension.*/
+        k0=_k;
+        do p=CELT_PVQ_U_ROW[--_k][_n];
+        while(p>_i);
+        _i-=p;
+        val=(k0-_k+s)^s;
+        *_y++=val;
+        yy=MAC16_16(yy,val,val);
+      }
+    }
+    _n--;
+  }
+  /*_n==2*/
+  p=2*_k+1;
+  s=-(_i>=p);
+  _i-=p&s;
+  k0=_k;
+  _k=(_i+1)>>1;
+  if(_k)_i-=2*_k-1;
+  val=(k0-_k+s)^s;
+  *_y++=val;
+  yy=MAC16_16(yy,val,val);
+  /*_n==1*/
+  s=-(int)_i;
+  val=(_k+s)^s;
+  *_y=val;
+  yy=MAC16_16(yy,val,val);
+  return yy;
+}
+
+opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
+  return cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y);
+}
+
+#else /* SMALL_FOOTPRINT */
+
+/*Computes the next row/column of any recurrence that obeys the relation
+   u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
+  _ui0 is the base case for the new row/column.*/
+static OPUS_INLINE void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){
+  opus_uint32 ui1;
+  unsigned      j;
+  /*This do-while will overrun the array if we don't have storage for at least
+     2 values.*/
+  j=1; do {
+    ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
+    _ui[j-1]=_ui0;
+    _ui0=ui1;
+  } while (++j<_len);
+  _ui[j-1]=_ui0;
+}
+
+/*Computes the previous row/column of any recurrence that obeys the relation
+   u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
+  _ui0 is the base case for the new row/column.*/
+static OPUS_INLINE void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){
+  opus_uint32 ui1;
+  unsigned      j;
+  /*This do-while will overrun the array if we don't have storage for at least
+     2 values.*/
+  j=1; do {
+    ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
+    _ui[j-1]=_ui0;
+    _ui0=ui1;
+  } while (++j<_n);
+  _ui[j-1]=_ui0;
+}
+
+/*Compute V(_n,_k), as well as U(_n,0..._k+1).
+  _u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/
+static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){
+  opus_uint32 um2;
+  unsigned      len;
+  unsigned      k;
+  len=_k+2;
+  /*We require storage at least 3 values (e.g., _k>0).*/
+  celt_assert(len>=3);
+  _u[0]=0;
+  _u[1]=um2=1;
+  /*If _n==0, _u[0] should be 1 and the rest should be 0.*/
+  /*If _n==1, _u[i] should be 1 for i>1.*/
+  celt_assert(_n>=2);
+  /*If _k==0, the following do-while loop will overflow the buffer.*/
+  celt_assert(_k>0);
+  k=2;
+  do _u[k]=(k<<1)-1;
+  while(++k<len);
+  for(k=2;k<_n;k++)unext(_u+1,_k+1,1);
+  return _u[_k]+_u[_k+1];
+}
+
+/*Returns the _i'th combination of _k elements chosen from a set of size _n
+   with associated sign bits.
+  _y: Returns the vector of pulses.
+  _u: Must contain entries [0..._k+1] of row _n of U() on input.
+      Its contents will be destructively modified.*/
+static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){
+  int j;
+  opus_int16 val;
+  opus_val32 yy=0;
+  celt_assert(_n>0);
+  j=0;
+  do{
+    opus_uint32 p;
+    int           s;
+    int           yj;
+    p=_u[_k+1];
+    s=-(_i>=p);
+    _i-=p&s;
+    yj=_k;
+    p=_u[_k];
+    while(p>_i)p=_u[--_k];
+    _i-=p;
+    yj-=_k;
+    val=(yj+s)^s;
+    _y[j]=val;
+    yy=MAC16_16(yy,val,val);
+    uprev(_u,_k+2,0);
+  }
+  while(++j<_n);
+  return yy;
+}
+
+/*Returns the index of the given combination of K elements chosen from a set
+   of size 1 with associated sign bits.
+  _y: The vector of pulses, whose sum of absolute values is K.
+  _k: Returns K.*/
+static OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){
+  *_k=abs(_y[0]);
+  return _y[0]<0;
+}
+
+/*Returns the index of the given combination of K elements chosen from a set
+   of size _n with associated sign bits.
+  _y:  The vector of pulses, whose sum of absolute values must be _k.
+  _nc: Returns V(_n,_k).*/
+static OPUS_INLINE opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y,
+ opus_uint32 *_u){
+  opus_uint32 i;
+  int         j;
+  int         k;
+  /*We can't unroll the first two iterations of the loop unless _n>=2.*/
+  celt_assert(_n>=2);
+  _u[0]=0;
+  for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1;
+  i=icwrs1(_y+_n-1,&k);
+  j=_n-2;
+  i+=_u[k];
+  k+=abs(_y[j]);
+  if(_y[j]<0)i+=_u[k+1];
+  while(j-->0){
+    unext(_u,_k+2,0);
+    i+=_u[k];
+    k+=abs(_y[j]);
+    if(_y[j]<0)i+=_u[k+1];
+  }
+  *_nc=_u[k]+_u[k+1];
+  return i;
+}
+
+#if defined(CUSTOM_MODES)
+void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
+  int k;
+  /*_maxk==0 => there's nothing to do.*/
+  celt_assert(_maxk>0);
+  _bits[0]=0;
+  if (_n==1)
+  {
+    for (k=1;k<=_maxk;k++)
+      _bits[k] = 1<<_frac;
+  }
+  else {
+    VARDECL(opus_uint32,u);
+    SAVE_STACK;
+    ALLOC(u,_maxk+2U,opus_uint32);
+    ncwrs_urow(_n,_maxk,u);
+    for(k=1;k<=_maxk;k++)
+      _bits[k]=log2_frac(u[k]+u[k+1],_frac);
+    RESTORE_STACK;
+  }
+}
+#endif /* CUSTOM_MODES */
+
+void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
+  opus_uint32 i;
+  VARDECL(opus_uint32,u);
+  opus_uint32 nc;
+  SAVE_STACK;
+  celt_assert(_k>0);
+  ALLOC(u,_k+2U,opus_uint32);
+  i=icwrs(_n,_k,&nc,_y,u);
+  ec_enc_uint(_enc,i,nc);
+  RESTORE_STACK;
+}
+
+opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
+  VARDECL(opus_uint32,u);
+  int ret;
+  SAVE_STACK;
+  celt_assert(_k>0);
+  ALLOC(u,_k+2U,opus_uint32);
+  ret = cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
+  RESTORE_STACK;
+  return ret;
+}
+
+#endif /* SMALL_FOOTPRINT */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/cwrs.h
new file mode 100644 (file)
index 0000000..7cd4717
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2007-2009 Timothy B. Terriberry
+   Written by Timothy B. Terriberry and Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CWRS_H
+#define CWRS_H
+
+#include "arch.h"
+#include "stack_alloc.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef CUSTOM_MODES
+int log2_frac(opus_uint32 val, int frac);
+#endif
+
+void get_required_bits(opus_int16 *bits, int N, int K, int frac);
+
+void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
+
+opus_val32 decode_pulses(int *_y, int N, int K, ec_dec *dec);
+
+#endif /* CWRS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/ecintrin.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/ecintrin.h
new file mode 100644 (file)
index 0000000..66a4c36
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright (c) 2003-2008 Timothy B. Terriberry
+   Copyright (c) 2008 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*Some common macros for potential platform-specific optimization.*/
+#include "opus_types.h"
+#include <math.h>
+#include <limits.h>
+#include "arch.h"
+#if !defined(_ecintrin_H)
+# define _ecintrin_H (1)
+
+/*Some specific platforms may have optimized intrinsic or OPUS_INLINE assembly
+   versions of these functions which can substantially improve performance.
+  We define macros for them to allow easy incorporation of these non-ANSI
+   features.*/
+
+/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
+   given an appropriate architecture, but the branchless bit-twiddling versions
+   are just as fast, and do not require any special target architecture.
+  Earlier gcc versions (3.x) compiled both code to the same assembly
+   instructions, because of the way they represented ((_b)>(_a)) internally.*/
+# define EC_MINI(_a,_b)      ((_a)+(((_b)-(_a))&-((_b)<(_a))))
+
+/*Count leading zeros.
+  This macro should only be used for implementing ec_ilog(), if it is defined.
+  All other code should use EC_ILOG() instead.*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#if defined(_MSC_VER) && (_MSC_VER >= 1910)
+# include <intrin0.h> /* Improve compiler throughput. */
+#else
+# include <intrin.h>
+#endif
+/*In _DEBUG mode this is not an intrinsic by default.*/
+# pragma intrinsic(_BitScanReverse)
+
+static __inline int ec_bsr(unsigned long _x){
+  unsigned long ret;
+  _BitScanReverse(&ret,_x);
+  return (int)ret;
+}
+# define EC_CLZ0    (1)
+# define EC_CLZ(_x) (-ec_bsr(_x))
+#elif defined(ENABLE_TI_DSPLIB)
+# include "dsplib.h"
+# define EC_CLZ0    (31)
+# define EC_CLZ(_x) (_lnorm(_x))
+#elif __GNUC_PREREQ(3,4)
+# if INT_MAX>=2147483647
+#  define EC_CLZ0    ((int)sizeof(unsigned)*CHAR_BIT)
+#  define EC_CLZ(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=2147483647L
+#  define EC_CLZ0    ((int)sizeof(unsigned long)*CHAR_BIT)
+#  define EC_CLZ(_x) (__builtin_clzl(_x))
+# endif
+#endif
+
+#if defined(EC_CLZ)
+/*Note that __builtin_clz is not defined when _x==0, according to the gcc
+   documentation (and that of the BSR instruction that implements it on x86).
+  The majority of the time we can never pass it zero.
+  When we need to, it can be special cased.*/
+# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
+#else
+int ec_ilog(opus_uint32 _v);
+# define EC_ILOG(_x) (ec_ilog(_x))
+#endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.c
new file mode 100644 (file)
index 0000000..70f3201
--- /dev/null
@@ -0,0 +1,153 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "entcode.h"
+#include "arch.h"
+
+#if !defined(EC_CLZ)
+/*This is a fallback for systems where we don't know how to access
+   a BSR or CLZ instruction (see ecintrin.h).
+  If you are optimizing Opus on a new platform and it has a native CLZ or
+   BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be
+   an easy performance win.*/
+int ec_ilog(opus_uint32 _v){
+  /*On a Pentium M, this branchless version tested as the fastest on
+     1,000,000,000 random 32-bit integers, edging out a similar version with
+     branches, and a 256-entry LUT version.*/
+  int ret;
+  int m;
+  ret=!!_v;
+  m=!!(_v&0xFFFF0000)<<4;
+  _v>>=m;
+  ret|=m;
+  m=!!(_v&0xFF00)<<3;
+  _v>>=m;
+  ret|=m;
+  m=!!(_v&0xF0)<<2;
+  _v>>=m;
+  ret|=m;
+  m=!!(_v&0xC)<<1;
+  _v>>=m;
+  ret|=m;
+  ret+=!!(_v&0x2);
+  return ret;
+}
+#endif
+
+#if 1
+/* This is a faster version of ec_tell_frac() that takes advantage
+   of the low (1/8 bit) resolution to use just a linear function
+   followed by a lookup to determine the exact transition thresholds. */
+opus_uint32 ec_tell_frac(ec_ctx *_this){
+  static const unsigned correction[8] =
+    {35733, 38967, 42495, 46340,
+     50535, 55109, 60097, 65535};
+  opus_uint32 nbits;
+  opus_uint32 r;
+  int         l;
+  unsigned    b;
+  nbits=_this->nbits_total<<BITRES;
+  l=EC_ILOG(_this->rng);
+  r=_this->rng>>(l-16);
+  b = (r>>12)-8;
+  b += r>correction[b];
+  l = (l<<3)+b;
+  return nbits-l;
+}
+#else
+opus_uint32 ec_tell_frac(ec_ctx *_this){
+  opus_uint32 nbits;
+  opus_uint32 r;
+  int         l;
+  int         i;
+  /*To handle the non-integral number of bits still left in the encoder/decoder
+     state, we compute the worst-case number of bits of val that must be
+     encoded to ensure that the value is inside the range for any possible
+     subsequent bits.
+    The computation here is independent of val itself (the decoder does not
+     even track that value), even though the real number of bits used after
+     ec_enc_done() may be 1 smaller if rng is a power of two and the
+     corresponding trailing bits of val are all zeros.
+    If we did try to track that special case, then coding a value with a
+     probability of 1/(1<<n) might sometimes appear to use more than n bits.
+    This may help explain the surprising result that a newly initialized
+     encoder or decoder claims to have used 1 bit.*/
+  nbits=_this->nbits_total<<BITRES;
+  l=EC_ILOG(_this->rng);
+  r=_this->rng>>(l-16);
+  for(i=BITRES;i-->0;){
+    int b;
+    r=r*r>>15;
+    b=(int)(r>>16);
+    l=l<<1|b;
+    r>>=b;
+  }
+  return nbits-l;
+}
+#endif
+
+#ifdef USE_SMALL_DIV_TABLE
+/* Result of 2^32/(2*i+1), except for i=0. */
+const opus_uint32 SMALL_DIV_TABLE[129] = {
+   0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924,
+   0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111,
+   0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C,
+   0x0A3D70A3, 0x097B425E, 0x08D3DCB0, 0x08421084,
+   0x07C1F07C, 0x07507507, 0x06EB3E45, 0x06906906,
+   0x063E7063, 0x05F417D0, 0x05B05B05, 0x0572620A,
+   0x05397829, 0x05050505, 0x04D4873E, 0x04A7904A,
+   0x047DC11F, 0x0456C797, 0x04325C53, 0x04104104,
+   0x03F03F03, 0x03D22635, 0x03B5CC0E, 0x039B0AD1,
+   0x0381C0E0, 0x0369D036, 0x03531DEC, 0x033D91D2,
+   0x0329161F, 0x03159721, 0x03030303, 0x02F14990,
+   0x02E05C0B, 0x02D02D02, 0x02C0B02C, 0x02B1DA46,
+   0x02A3A0FD, 0x0295FAD4, 0x0288DF0C, 0x027C4597,
+   0x02702702, 0x02647C69, 0x02593F69, 0x024E6A17,
+   0x0243F6F0, 0x0239E0D5, 0x02302302, 0x0226B902,
+   0x021D9EAD, 0x0214D021, 0x020C49BA, 0x02040810,
+   0x01FC07F0, 0x01F44659, 0x01ECC07B, 0x01E573AC,
+   0x01DE5D6E, 0x01D77B65, 0x01D0CB58, 0x01CA4B30,
+   0x01C3F8F0, 0x01BDD2B8, 0x01B7D6C3, 0x01B20364,
+   0x01AC5701, 0x01A6D01A, 0x01A16D3F, 0x019C2D14,
+   0x01970E4F, 0x01920FB4, 0x018D3018, 0x01886E5F,
+   0x0183C977, 0x017F405F, 0x017AD220, 0x01767DCE,
+   0x01724287, 0x016E1F76, 0x016A13CD, 0x01661EC6,
+   0x01623FA7, 0x015E75BB, 0x015AC056, 0x01571ED3,
+   0x01539094, 0x01501501, 0x014CAB88, 0x0149539E,
+   0x01460CBC, 0x0142D662, 0x013FB013, 0x013C995A,
+   0x013991C2, 0x013698DF, 0x0133AE45, 0x0130D190,
+   0x012E025C, 0x012B404A, 0x01288B01, 0x0125E227,
+   0x01234567, 0x0120B470, 0x011E2EF3, 0x011BB4A4,
+   0x01194538, 0x0116E068, 0x011485F0, 0x0112358E,
+   0x010FEF01, 0x010DB20A, 0x010B7E6E, 0x010953F3,
+   0x01073260, 0x0105197F, 0x0103091B, 0x01010101
+};
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entcode.h
new file mode 100644 (file)
index 0000000..de145c7
--- /dev/null
@@ -0,0 +1,152 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if !defined(_entcode_H)
+# define _entcode_H (1)
+# include <limits.h>
+# include <stddef.h>
+# include "ecintrin.h"
+
+extern const opus_uint32 SMALL_DIV_TABLE[129];
+
+#ifdef OPUS_ARM_ASM
+#define USE_SMALL_DIV_TABLE
+#endif
+
+/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a
+   larger type, you can speed up the decoder by using it here.*/
+typedef opus_uint32           ec_window;
+typedef struct ec_ctx         ec_ctx;
+typedef struct ec_ctx         ec_enc;
+typedef struct ec_ctx         ec_dec;
+
+# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
+
+/*The number of bits to use for the range-coded part of unsigned integers.*/
+# define EC_UINT_BITS   (8)
+
+/*The resolution of fractional-precision bit usage measurements, i.e.,
+   3 => 1/8th bits.*/
+# define BITRES 3
+
+/*The entropy encoder/decoder context.
+  We use the same structure for both, so that common functions like ec_tell()
+   can be used on either one.*/
+struct ec_ctx{
+   /*Buffered input/output.*/
+   unsigned char *buf;
+   /*The size of the buffer.*/
+   opus_uint32    storage;
+   /*The offset at which the last byte containing raw bits was read/written.*/
+   opus_uint32    end_offs;
+   /*Bits that will be read from/written at the end.*/
+   ec_window      end_window;
+   /*Number of valid bits in end_window.*/
+   int            nend_bits;
+   /*The total number of whole bits read/written.
+     This does not include partial bits currently in the range coder.*/
+   int            nbits_total;
+   /*The offset at which the next range coder byte will be read/written.*/
+   opus_uint32    offs;
+   /*The number of values in the current range.*/
+   opus_uint32    rng;
+   /*In the decoder: the difference between the top of the current range and
+      the input value, minus one.
+     In the encoder: the low end of the current range.*/
+   opus_uint32    val;
+   /*In the decoder: the saved normalization factor from ec_decode().
+     In the encoder: the number of outstanding carry propagating symbols.*/
+   opus_uint32    ext;
+   /*A buffered input/output symbol, awaiting carry propagation.*/
+   int            rem;
+   /*Nonzero if an error occurred.*/
+   int            error;
+};
+
+static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){
+  return _this->offs;
+}
+
+static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){
+  return _this->buf;
+}
+
+static OPUS_INLINE int ec_get_error(ec_ctx *_this){
+  return _this->error;
+}
+
+/*Returns the number of bits "used" by the encoded or decoded symbols so far.
+  This same number can be computed in either the encoder or the decoder, and is
+   suitable for making coding decisions.
+  Return: The number of bits.
+          This will always be slightly larger than the exact value (e.g., all
+           rounding error is in the positive direction).*/
+static OPUS_INLINE int ec_tell(ec_ctx *_this){
+  return _this->nbits_total-EC_ILOG(_this->rng);
+}
+
+/*Returns the number of bits "used" by the encoded or decoded symbols so far.
+  This same number can be computed in either the encoder or the decoder, and is
+   suitable for making coding decisions.
+  Return: The number of bits scaled by 2**BITRES.
+          This will always be slightly larger than the exact value (e.g., all
+           rounding error is in the positive direction).*/
+opus_uint32 ec_tell_frac(ec_ctx *_this);
+
+/* Tested exhaustively for all n and for 1<=d<=256 */
+static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
+   celt_sig_assert(d>0);
+#ifdef USE_SMALL_DIV_TABLE
+   if (d>256)
+      return n/d;
+   else {
+      opus_uint32 t, q;
+      t = EC_ILOG(d&-d);
+      q = (opus_uint64)SMALL_DIV_TABLE[d>>t]*(n>>(t-1))>>32;
+      return q+(n-q*d >= d);
+   }
+#else
+   return n/d;
+#endif
+}
+
+static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
+   celt_sig_assert(d>0);
+#ifdef USE_SMALL_DIV_TABLE
+   if (n<0)
+      return -(opus_int32)celt_udiv(-n, d);
+   else
+      return celt_udiv(n, d);
+#else
+   return n/d;
+#endif
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.c
new file mode 100644 (file)
index 0000000..027aa24
--- /dev/null
@@ -0,0 +1,266 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include "os_support.h"
+#include "arch.h"
+#include "entdec.h"
+#include "mfrngcod.h"
+
+/*A range decoder.
+  This is an entropy decoder based upon \cite{Mar79}, which is itself a
+   rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
+  It is very similar to arithmetic encoding, except that encoding is done with
+   digits in any base, instead of with bits, and so it is faster when using
+   larger bases (i.e.: a byte).
+  The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
+   is the base, longer than the theoretical optimum, but to my knowledge there
+   is no published justification for this claim.
+  This only seems true when using near-infinite precision arithmetic so that
+   the process is carried out with no rounding errors.
+
+  An excellent description of implementation details is available at
+   http://www.arturocampos.com/ac_range.html
+  A recent work \cite{MNW98} which proposes several changes to arithmetic
+   encoding for efficiency actually re-discovers many of the principles
+   behind range encoding, and presents a good theoretical analysis of them.
+
+  End of stream is handled by writing out the smallest number of bits that
+   ensures that the stream will be correctly decoded regardless of the value of
+   any subsequent bits.
+  ec_tell() can be used to determine how many bits were needed to decode
+   all the symbols thus far; other data can be packed in the remaining bits of
+   the input buffer.
+  @PHDTHESIS{Pas76,
+    author="Richard Clark Pasco",
+    title="Source coding algorithms for fast data compression",
+    school="Dept. of Electrical Engineering, Stanford University",
+    address="Stanford, CA",
+    month=May,
+    year=1976
+  }
+  @INPROCEEDINGS{Mar79,
+   author="Martin, G.N.N.",
+   title="Range encoding: an algorithm for removing redundancy from a digitised
+    message",
+   booktitle="Video & Data Recording Conference",
+   year=1979,
+   address="Southampton",
+   month=Jul
+  }
+  @ARTICLE{MNW98,
+   author="Alistair Moffat and Radford Neal and Ian H. Witten",
+   title="Arithmetic Coding Revisited",
+   journal="{ACM} Transactions on Information Systems",
+   year=1998,
+   volume=16,
+   number=3,
+   pages="256--294",
+   month=Jul,
+   URL="http://www.stanford.edu/class/ee398a/handouts/papers/Moffat98ArithmCoding.pdf"
+  }*/
+
+static int ec_read_byte(ec_dec *_this){
+  return _this->offs<_this->storage?_this->buf[_this->offs++]:0;
+}
+
+static int ec_read_byte_from_end(ec_dec *_this){
+  return _this->end_offs<_this->storage?
+   _this->buf[_this->storage-++(_this->end_offs)]:0;
+}
+
+/*Normalizes the contents of val and rng so that rng lies entirely in the
+   high-order symbol.*/
+static void ec_dec_normalize(ec_dec *_this){
+  /*If the range is too small, rescale it and input some bits.*/
+  while(_this->rng<=EC_CODE_BOT){
+    int sym;
+    _this->nbits_total+=EC_SYM_BITS;
+    _this->rng<<=EC_SYM_BITS;
+    /*Use up the remaining bits from our last symbol.*/
+    sym=_this->rem;
+    /*Read the next value from the input.*/
+    _this->rem=ec_read_byte(_this);
+    /*Take the rest of the bits we need from this new symbol.*/
+    sym=(sym<<EC_SYM_BITS|_this->rem)>>(EC_SYM_BITS-EC_CODE_EXTRA);
+    /*And subtract them from val, capped to be less than EC_CODE_TOP.*/
+    _this->val=((_this->val<<EC_SYM_BITS)+(EC_SYM_MAX&~sym))&(EC_CODE_TOP-1);
+  }
+}
+
+void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage){
+  _this->buf=_buf;
+  _this->storage=_storage;
+  _this->end_offs=0;
+  _this->end_window=0;
+  _this->nend_bits=0;
+  /*This is the offset from which ec_tell() will subtract partial bits.
+    The final value after the ec_dec_normalize() call will be the same as in
+     the encoder, but we have to compensate for the bits that are added there.*/
+  _this->nbits_total=EC_CODE_BITS+1
+   -((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS;
+  _this->offs=0;
+  _this->rng=1U<<EC_CODE_EXTRA;
+  _this->rem=ec_read_byte(_this);
+  _this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA));
+  _this->error=0;
+  /*Normalize the interval.*/
+  ec_dec_normalize(_this);
+}
+
+unsigned ec_decode(ec_dec *_this,unsigned _ft){
+  unsigned s;
+  _this->ext=celt_udiv(_this->rng,_ft);
+  s=(unsigned)(_this->val/_this->ext);
+  return _ft-EC_MINI(s+1,_ft);
+}
+
+unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){
+   unsigned s;
+   _this->ext=_this->rng>>_bits;
+   s=(unsigned)(_this->val/_this->ext);
+   return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits);
+}
+
+void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
+  opus_uint32 s;
+  s=IMUL32(_this->ext,_ft-_fh);
+  _this->val-=s;
+  _this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s;
+  ec_dec_normalize(_this);
+}
+
+/*The probability of having a "one" is 1/(1<<_logp).*/
+int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){
+  opus_uint32 r;
+  opus_uint32 d;
+  opus_uint32 s;
+  int         ret;
+  r=_this->rng;
+  d=_this->val;
+  s=r>>_logp;
+  ret=d<s;
+  if(!ret)_this->val=d-s;
+  _this->rng=ret?s:r-s;
+  ec_dec_normalize(_this);
+  return ret;
+}
+
+int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
+  opus_uint32 r;
+  opus_uint32 d;
+  opus_uint32 s;
+  opus_uint32 t;
+  int         ret;
+  s=_this->rng;
+  d=_this->val;
+  r=s>>_ftb;
+  ret=-1;
+  do{
+    t=s;
+    s=IMUL32(r,_icdf[++ret]);
+  }
+  while(d<s);
+  _this->val=d-s;
+  _this->rng=t-s;
+  ec_dec_normalize(_this);
+  return ret;
+}
+
+int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb){
+  opus_uint32 r;
+  opus_uint32 d;
+  opus_uint32 s;
+  opus_uint32 t;
+  int         ret;
+  s=_this->rng;
+  d=_this->val;
+  r=s>>_ftb;
+  ret=-1;
+  do{
+    t=s;
+    s=IMUL32(r,_icdf[++ret]);
+  }
+  while(d<s);
+  _this->val=d-s;
+  _this->rng=t-s;
+  ec_dec_normalize(_this);
+  return ret;
+}
+
+opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
+  unsigned ft;
+  unsigned s;
+  int      ftb;
+  /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
+  celt_assert(_ft>1);
+  _ft--;
+  ftb=EC_ILOG(_ft);
+  if(ftb>EC_UINT_BITS){
+    opus_uint32 t;
+    ftb-=EC_UINT_BITS;
+    ft=(unsigned)(_ft>>ftb)+1;
+    s=ec_decode(_this,ft);
+    ec_dec_update(_this,s,s+1,ft);
+    t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb);
+    if(t<=_ft)return t;
+    _this->error=1;
+    return _ft;
+  }
+  else{
+    _ft++;
+    s=ec_decode(_this,(unsigned)_ft);
+    ec_dec_update(_this,s,s+1,(unsigned)_ft);
+    return s;
+  }
+}
+
+opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
+  ec_window   window;
+  int         available;
+  opus_uint32 ret;
+  window=_this->end_window;
+  available=_this->nend_bits;
+  if((unsigned)available<_bits){
+    do{
+      window|=(ec_window)ec_read_byte_from_end(_this)<<available;
+      available+=EC_SYM_BITS;
+    }
+    while(available<=EC_WINDOW_SIZE-EC_SYM_BITS);
+  }
+  ret=(opus_uint32)window&(((opus_uint32)1<<_bits)-1U);
+  window>>=_bits;
+  available-=_bits;
+  _this->end_window=window;
+  _this->nend_bits=available;
+  _this->nbits_total+=_bits;
+  return ret;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entdec.h
new file mode 100644 (file)
index 0000000..c81f26f
--- /dev/null
@@ -0,0 +1,110 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if !defined(_entdec_H)
+# define _entdec_H (1)
+# include <limits.h>
+# include "entcode.h"
+
+/*Initializes the decoder.
+  _buf: The input buffer to use.
+  Return: 0 on success, or a negative value on error.*/
+void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage);
+
+/*Calculates the cumulative frequency for the next symbol.
+  This can then be fed into the probability model to determine what that
+   symbol is, and the additional frequency information required to advance to
+   the next symbol.
+  This function cannot be called more than once without a corresponding call to
+   ec_dec_update(), or decoding will not proceed correctly.
+  _ft: The total frequency of the symbols in the alphabet the next symbol was
+        encoded with.
+  Return: A cumulative frequency representing the encoded symbol.
+          If the cumulative frequency of all the symbols before the one that
+           was encoded was fl, and the cumulative frequency of all the symbols
+           up to and including the one encoded is fh, then the returned value
+           will fall in the range [fl,fh).*/
+unsigned ec_decode(ec_dec *_this,unsigned _ft);
+
+/*Equivalent to ec_decode() with _ft==1<<_bits.*/
+unsigned ec_decode_bin(ec_dec *_this,unsigned _bits);
+
+/*Advance the decoder past the next symbol using the frequency information the
+   symbol was encoded with.
+  Exactly one call to ec_decode() must have been made so that all necessary
+   intermediate calculations are performed.
+  _fl:  The cumulative frequency of all symbols that come before the symbol
+         decoded.
+  _fh:  The cumulative frequency of all symbols up to and including the symbol
+         decoded.
+        Together with _fl, this defines the range [_fl,_fh) in which the value
+         returned above must fall.
+  _ft:  The total frequency of the symbols in the alphabet the symbol decoded
+         was encoded in.
+        This must be the same as passed to the preceding call to ec_decode().*/
+void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft);
+
+/* Decode a bit that has a 1/(1<<_logp) probability of being a one */
+int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
+
+/*Decodes a symbol given an "inverse" CDF table.
+  No call to ec_dec_update() is necessary after this call.
+  _icdf: The "inverse" CDF, such that symbol s falls in the range
+          [s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
+         The values must be monotonically non-increasing, and the last value
+          must be 0.
+  _ftb: The number of bits of precision in the cumulative distribution.
+  Return: The decoded symbol s.*/
+int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
+
+/*Decodes a symbol given an "inverse" CDF table.
+  No call to ec_dec_update() is necessary after this call.
+  _icdf: The "inverse" CDF, such that symbol s falls in the range
+          [s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
+         The values must be monotonically non-increasing, and the last value
+          must be 0.
+  _ftb: The number of bits of precision in the cumulative distribution.
+  Return: The decoded symbol s.*/
+int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb);
+
+/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
+  The bits must have been encoded with ec_enc_uint().
+  No call to ec_dec_update() is necessary after this call.
+  _ft: The number of integers that can be decoded (one more than the max).
+       This must be at least 2, and no more than 2**32-1.
+  Return: The decoded bits.*/
+opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
+
+/*Extracts a sequence of raw bits from the stream.
+  The bits must have been encoded with ec_enc_bits().
+  No call to ec_dec_update() is necessary after this call.
+  _ftb: The number of bits to extract.
+        This must be between 0 and 25, inclusive.
+  Return: The decoded bits.*/
+opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.c
new file mode 100644 (file)
index 0000000..ede00c8
--- /dev/null
@@ -0,0 +1,305 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if defined(HAVE_CONFIG_H)
+# include "config.h"
+#endif
+#include "os_support.h"
+#include "arch.h"
+#include "entenc.h"
+#include "mfrngcod.h"
+
+/*A range encoder.
+  See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
+
+  @INPROCEEDINGS{Mar79,
+   author="Martin, G.N.N.",
+   title="Range encoding: an algorithm for removing redundancy from a digitised
+    message",
+   booktitle="Video \& Data Recording Conference",
+   year=1979,
+   address="Southampton",
+   month=Jul
+  }
+  @ARTICLE{MNW98,
+   author="Alistair Moffat and Radford Neal and Ian H. Witten",
+   title="Arithmetic Coding Revisited",
+   journal="{ACM} Transactions on Information Systems",
+   year=1998,
+   volume=16,
+   number=3,
+   pages="256--294",
+   month=Jul,
+   URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
+  }*/
+
+static int ec_write_byte(ec_enc *_this,unsigned _value){
+  if(_this->offs+_this->end_offs>=_this->storage)return -1;
+  _this->buf[_this->offs++]=(unsigned char)_value;
+  return 0;
+}
+
+static int ec_write_byte_at_end(ec_enc *_this,unsigned _value){
+  if(_this->offs+_this->end_offs>=_this->storage)return -1;
+  _this->buf[_this->storage-++(_this->end_offs)]=(unsigned char)_value;
+  return 0;
+}
+
+/*Outputs a symbol, with a carry bit.
+  If there is a potential to propagate a carry over several symbols, they are
+   buffered until it can be determined whether or not an actual carry will
+   occur.
+  If the counter for the buffered symbols overflows, then the stream becomes
+   undecodable.
+  This gives a theoretical limit of a few billion symbols in a single packet on
+   32-bit systems.
+  The alternative is to truncate the range in order to force a carry, but
+   requires similar carry tracking in the decoder, needlessly slowing it down.*/
+static void ec_enc_carry_out(ec_enc *_this,int _c){
+  if(_c!=EC_SYM_MAX){
+    /*No further carry propagation possible, flush buffer.*/
+    int carry;
+    carry=_c>>EC_SYM_BITS;
+    /*Don't output a byte on the first write.
+      This compare should be taken care of by branch-prediction thereafter.*/
+    if(_this->rem>=0)_this->error|=ec_write_byte(_this,_this->rem+carry);
+    if(_this->ext>0){
+      unsigned sym;
+      sym=(EC_SYM_MAX+carry)&EC_SYM_MAX;
+      do _this->error|=ec_write_byte(_this,sym);
+      while(--(_this->ext)>0);
+    }
+    _this->rem=_c&EC_SYM_MAX;
+  }
+  else _this->ext++;
+}
+
+static OPUS_INLINE void ec_enc_normalize(ec_enc *_this){
+  /*If the range is too small, output some bits and rescale it.*/
+  while(_this->rng<=EC_CODE_BOT){
+    ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT));
+    /*Move the next-to-high-order symbol into the high-order position.*/
+    _this->val=(_this->val<<EC_SYM_BITS)&(EC_CODE_TOP-1);
+    _this->rng<<=EC_SYM_BITS;
+    _this->nbits_total+=EC_SYM_BITS;
+  }
+}
+
+void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size){
+  _this->buf=_buf;
+  _this->end_offs=0;
+  _this->end_window=0;
+  _this->nend_bits=0;
+  /*This is the offset from which ec_tell() will subtract partial bits.*/
+  _this->nbits_total=EC_CODE_BITS+1;
+  _this->offs=0;
+  _this->rng=EC_CODE_TOP;
+  _this->rem=-1;
+  _this->val=0;
+  _this->ext=0;
+  _this->storage=_size;
+  _this->error=0;
+}
+
+void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
+  opus_uint32 r;
+  r=celt_udiv(_this->rng,_ft);
+  if(_fl>0){
+    _this->val+=_this->rng-IMUL32(r,(_ft-_fl));
+    _this->rng=IMUL32(r,(_fh-_fl));
+  }
+  else _this->rng-=IMUL32(r,(_ft-_fh));
+  ec_enc_normalize(_this);
+}
+
+void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits){
+  opus_uint32 r;
+  r=_this->rng>>_bits;
+  if(_fl>0){
+    _this->val+=_this->rng-IMUL32(r,((1U<<_bits)-_fl));
+    _this->rng=IMUL32(r,(_fh-_fl));
+  }
+  else _this->rng-=IMUL32(r,((1U<<_bits)-_fh));
+  ec_enc_normalize(_this);
+}
+
+/*The probability of having a "one" is 1/(1<<_logp).*/
+void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){
+  opus_uint32 r;
+  opus_uint32 s;
+  opus_uint32 l;
+  r=_this->rng;
+  l=_this->val;
+  s=r>>_logp;
+  r-=s;
+  if(_val)_this->val=l+r;
+  _this->rng=_val?s:r;
+  ec_enc_normalize(_this);
+}
+
+void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){
+  opus_uint32 r;
+  r=_this->rng>>_ftb;
+  if(_s>0){
+    _this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
+    _this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
+  }
+  else _this->rng-=IMUL32(r,_icdf[_s]);
+  ec_enc_normalize(_this);
+}
+
+void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb){
+  opus_uint32 r;
+  r=_this->rng>>_ftb;
+  if(_s>0){
+    _this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
+    _this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
+  }
+  else _this->rng-=IMUL32(r,_icdf[_s]);
+  ec_enc_normalize(_this);
+}
+
+void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){
+  unsigned  ft;
+  unsigned  fl;
+  int       ftb;
+  /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
+  celt_assert(_ft>1);
+  _ft--;
+  ftb=EC_ILOG(_ft);
+  if(ftb>EC_UINT_BITS){
+    ftb-=EC_UINT_BITS;
+    ft=(_ft>>ftb)+1;
+    fl=(unsigned)(_fl>>ftb);
+    ec_encode(_this,fl,fl+1,ft);
+    ec_enc_bits(_this,_fl&(((opus_uint32)1<<ftb)-1U),ftb);
+  }
+  else ec_encode(_this,_fl,_fl+1,_ft+1);
+}
+
+void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _bits){
+  ec_window window;
+  int       used;
+  window=_this->end_window;
+  used=_this->nend_bits;
+  celt_assert(_bits>0);
+  if(used+_bits>EC_WINDOW_SIZE){
+    do{
+      _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
+      window>>=EC_SYM_BITS;
+      used-=EC_SYM_BITS;
+    }
+    while(used>=EC_SYM_BITS);
+  }
+  window|=(ec_window)_fl<<used;
+  used+=_bits;
+  _this->end_window=window;
+  _this->nend_bits=used;
+  _this->nbits_total+=_bits;
+}
+
+void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits){
+  int      shift;
+  unsigned mask;
+  celt_assert(_nbits<=EC_SYM_BITS);
+  shift=EC_SYM_BITS-_nbits;
+  mask=((1<<_nbits)-1)<<shift;
+  if(_this->offs>0){
+    /*The first byte has been finalized.*/
+    _this->buf[0]=(unsigned char)((_this->buf[0]&~mask)|_val<<shift);
+  }
+  else if(_this->rem>=0){
+    /*The first byte is still awaiting carry propagation.*/
+    _this->rem=(_this->rem&~mask)|_val<<shift;
+  }
+  else if(_this->rng<=(EC_CODE_TOP>>_nbits)){
+    /*The renormalization loop has never been run.*/
+    _this->val=(_this->val&~((opus_uint32)mask<<EC_CODE_SHIFT))|
+     (opus_uint32)_val<<(EC_CODE_SHIFT+shift);
+  }
+  /*The encoder hasn't even encoded _nbits of data yet.*/
+  else _this->error=-1;
+}
+
+void ec_enc_shrink(ec_enc *_this,opus_uint32 _size){
+  celt_assert(_this->offs+_this->end_offs<=_size);
+  OPUS_MOVE(_this->buf+_size-_this->end_offs,
+   _this->buf+_this->storage-_this->end_offs,_this->end_offs);
+  _this->storage=_size;
+}
+
+void ec_enc_done(ec_enc *_this){
+  ec_window   window;
+  int         used;
+  opus_uint32 msk;
+  opus_uint32 end;
+  int         l;
+  /*We output the minimum number of bits that ensures that the symbols encoded
+     thus far will be decoded correctly regardless of the bits that follow.*/
+  l=EC_CODE_BITS-EC_ILOG(_this->rng);
+  msk=(EC_CODE_TOP-1)>>l;
+  end=(_this->val+msk)&~msk;
+  if((end|msk)>=_this->val+_this->rng){
+    l++;
+    msk>>=1;
+    end=(_this->val+msk)&~msk;
+  }
+  while(l>0){
+    ec_enc_carry_out(_this,(int)(end>>EC_CODE_SHIFT));
+    end=(end<<EC_SYM_BITS)&(EC_CODE_TOP-1);
+    l-=EC_SYM_BITS;
+  }
+  /*If we have a buffered byte flush it into the output buffer.*/
+  if(_this->rem>=0||_this->ext>0)ec_enc_carry_out(_this,0);
+  /*If we have buffered extra bits, flush them as well.*/
+  window=_this->end_window;
+  used=_this->nend_bits;
+  while(used>=EC_SYM_BITS){
+    _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
+    window>>=EC_SYM_BITS;
+    used-=EC_SYM_BITS;
+  }
+  /*Clear any excess space and add any remaining extra bits to the last byte.*/
+  if(!_this->error){
+    if (_this->buf) OPUS_CLEAR(_this->buf+_this->offs,
+     _this->storage-_this->offs-_this->end_offs);
+    if(used>0){
+      /*If there's no range coder data at all, give up.*/
+      if(_this->end_offs>=_this->storage)_this->error=-1;
+      else{
+        l=-l;
+        /*If we've busted, don't add too many extra bits to the last byte; it
+           would corrupt the range coder data, and that's more important.*/
+        if(_this->offs+_this->end_offs>=_this->storage&&l<used){
+          window&=(1<<l)-1;
+          _this->error=-1;
+        }
+        _this->buf[_this->storage-_this->end_offs-1]|=(unsigned char)window;
+      }
+    }
+  }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/entenc.h
new file mode 100644 (file)
index 0000000..c7bcf00
--- /dev/null
@@ -0,0 +1,119 @@
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if !defined(_entenc_H)
+# define _entenc_H (1)
+# include <stddef.h>
+# include "entcode.h"
+
+/*Initializes the encoder.
+  _buf:  The buffer to store output bytes in.
+  _size: The size of the buffer, in chars.*/
+void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size);
+/*Encodes a symbol given its frequency information.
+  The frequency information must be discernible by the decoder, assuming it
+   has read only the previous symbols from the stream.
+  It is allowable to change the frequency information, or even the entire
+   source alphabet, so long as the decoder can tell from the context of the
+   previously encoded information that it is supposed to do so as well.
+  _fl: The cumulative frequency of all symbols that come before the one to be
+        encoded.
+  _fh: The cumulative frequency of all symbols up to and including the one to
+        be encoded.
+       Together with _fl, this defines the range [_fl,_fh) in which the
+        decoded value will fall.
+  _ft: The sum of the frequencies of all the symbols*/
+void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft);
+
+/*Equivalent to ec_encode() with _ft==1<<_bits.*/
+void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits);
+
+/* Encode a bit that has a 1/(1<<_logp) probability of being a one */
+void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp);
+
+/*Encodes a symbol given an "inverse" CDF table.
+  _s:    The index of the symbol to encode.
+  _icdf: The "inverse" CDF, such that symbol _s falls in the range
+          [_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
+         The values must be monotonically non-increasing, and the last value
+          must be 0.
+  _ftb: The number of bits of precision in the cumulative distribution.*/
+void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
+
+/*Encodes a symbol given an "inverse" CDF table.
+  _s:    The index of the symbol to encode.
+  _icdf: The "inverse" CDF, such that symbol _s falls in the range
+          [_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
+         The values must be monotonically non-increasing, and the last value
+          must be 0.
+  _ftb: The number of bits of precision in the cumulative distribution.*/
+void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb);
+
+/*Encodes a raw unsigned integer in the stream.
+  _fl: The integer to encode.
+  _ft: The number of integers that can be encoded (one more than the max).
+       This must be at least 2, and no more than 2**32-1.*/
+void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
+
+/*Encodes a sequence of raw bits in the stream.
+  _fl:  The bits to encode.
+  _ftb: The number of bits to encode.
+        This must be between 1 and 25, inclusive.*/
+void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _ftb);
+
+/*Overwrites a few bits at the very start of an existing stream, after they
+   have already been encoded.
+  This makes it possible to have a few flags up front, where it is easy for
+   decoders to access them without parsing the whole stream, even if their
+   values are not determined until late in the encoding process, without having
+   to buffer all the intermediate symbols in the encoder.
+  In order for this to work, at least _nbits bits must have already been
+   encoded using probabilities that are an exact power of two.
+  The encoder can verify the number of encoded bits is sufficient, but cannot
+   check this latter condition.
+  _val:   The bits to encode (in the least _nbits significant bits).
+          They will be decoded in order from most-significant to least.
+  _nbits: The number of bits to overwrite.
+          This must be no more than 8.*/
+void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits);
+
+/*Compacts the data to fit in the target size.
+  This moves up the raw bits at the end of the current buffer so they are at
+   the end of the new buffer size.
+  The caller must ensure that the amount of data that's already been written
+   will fit in the new size.
+  _size: The number of bytes in the new buffer.
+         This must be large enough to contain the bits already written, and
+          must be no larger than the existing size.*/
+void ec_enc_shrink(ec_enc *_this,opus_uint32 _size);
+
+/*Indicates that there are no more symbols to encode.
+  All remaining output bytes are flushed to the output buffer.
+  ec_enc_init() must be called before the encoder can be used again.*/
+void ec_enc_done(ec_enc *_this);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_debug.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_debug.h
new file mode 100644 (file)
index 0000000..34c3646
--- /dev/null
@@ -0,0 +1,848 @@
+/* Copyright (C) 2003-2008 Jean-Marc Valin
+   Copyright (C) 2007-2012 Xiph.Org Foundation */
+/**
+   @file fixed_debug.h
+   @brief Fixed-point operations with debugging
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_DEBUG_H
+#define FIXED_DEBUG_H
+
+#include <stdio.h>
+#include "opus_defines.h"
+
+#ifdef CELT_C
+OPUS_EXPORT opus_int64 celt_mips=0;
+#else
+extern opus_int64 celt_mips;
+#endif
+
+#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b))
+#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
+#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
+#define MULT32_32_P31(a,b) ADD32(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
+
+/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
+
+#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
+
+#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
+#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val64)1)<<(bits))))
+#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
+#define GCONST(x) GCONST2((x),DB_SHIFT)
+
+#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
+#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
+#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
+
+#define SHR(a,b) SHR32(a,b)
+#define PSHR(a,b) PSHR32(a,b)
+
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
+/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
+#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
+
+static OPUS_INLINE short NEG16(int x)
+{
+   int res;
+   if (!VERIFY_SHORT(x))
+   {
+      fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = -x;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+static OPUS_INLINE int NEG32(opus_int64 x)
+{
+   opus_int64 res;
+   if (!VERIFY_INT(x))
+   {
+      fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = -x;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
+static OPUS_INLINE short EXTRACT16_(int x, char *file, int line)
+{
+   int res;
+   if (!VERIFY_SHORT(x))
+   {
+      fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = x;
+   celt_mips++;
+   return res;
+}
+
+#define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
+static OPUS_INLINE int EXTEND32_(int x, char *file, int line)
+{
+   int res;
+   if (!VERIFY_SHORT(x))
+   {
+      fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = x;
+   celt_mips++;
+   return res;
+}
+
+#define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE short SHR16_(int a, int shift, char *file, int line)
+{
+   int res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
+   {
+      fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a>>shift;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+#define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE short SHL16_(int a, int shift, char *file, int line)
+{
+   opus_int32 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
+   {
+      fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = (opus_int32)((opus_uint32)a<<shift);
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+
+static OPUS_INLINE int SHR32(opus_int64 a, int shift)
+{
+   opus_int64  res;
+   if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
+   {
+      fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a>>shift;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
+{
+   opus_int64  res;
+   if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
+   {
+      fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = (opus_int64)((opus_uint64)a<<shift);
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", (long long)a, shift, (long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+
+#define SHR64(a,shift) (celt_mips++,(a) >> (shift))
+
+#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
+#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
+
+#define HALF16(x)  (SHR16(x,1))
+#define HALF32(x)  (SHR32(x,1))
+
+#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
+{
+   int res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a+b;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+
+#define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short SUB16_(int a, int b, char *file, int line)
+{
+   int res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a-b;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+
+#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_INT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a+b;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_INT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a-b;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#undef UADD32
+#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
+{
+   opus_uint64 res;
+   if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
+   {
+      fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a+b;
+   if (!VERIFY_UINT(res))
+   {
+      fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", (unsigned long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#undef USUB32
+#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
+{
+   opus_uint64 res;
+   if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
+   {
+      fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   if (a<b)
+   {
+      fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a-b;
+   if (!VERIFY_UINT(res))
+   {
+      fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, (unsigned long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+/* result fits in 16 bits */
+static OPUS_INLINE short MULT16_16_16(int a, int b)
+{
+   int res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a*b;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+
+/* result fits in 32 bits */
+static OPUS_INLINE int MULT32_32_32(opus_int64 a, opus_int64 b)
+{
+   opus_int64 res;
+   if (!VERIFY_INT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "MULT32_32_32: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a*b;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT32_32_32: output is not int: %lld\n", (long long)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=5;
+   return res;
+}
+
+static OPUS_INLINE int MULT32_32_Q16(opus_int64 a, opus_int64 b)
+{
+   opus_int64 res;
+   if (!VERIFY_INT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "MULT32_32_Q16: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)(a)*(opus_int64)(b)) >> 16;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT32_32_Q16: output is not int: %lld*%lld=%lld\n", (long long)a, (long long)b, (long long)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=5;
+   return res;
+}
+
+#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_16_(int a, int b, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips++;
+   return res;
+}
+
+#define MAC16_16(c,a,b)     (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
+
+#define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
+   {
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = (((opus_int64)a)*(opus_int64)b) >> Q;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   if (Q==15)
+      celt_mips+=3;
+   else
+      celt_mips+=4;
+   return res;
+}
+
+#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
+   {
+      fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   if (Q==15)
+      celt_mips+=4;
+   else
+      celt_mips+=5;
+   return res;
+}
+
+#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
+#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
+#define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b))))
+
+static OPUS_INLINE int SATURATE(int a, int b)
+{
+   if (a>b)
+      a=b;
+   if (a<-b)
+      a = -b;
+   celt_mips+=3;
+   return a;
+}
+
+static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
+{
+   celt_mips+=3;
+   if (a>32767)
+      return 32767;
+   else if (a<-32768)
+      return -32768;
+   else return a;
+}
+
+static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res >>= 11;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=3;
+   return res;
+}
+static OPUS_INLINE short MULT16_16_Q13(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res >>= 13;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=3;
+   return res;
+}
+static OPUS_INLINE short MULT16_16_Q14(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res >>= 14;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=3;
+   return res;
+}
+
+#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res >>= 15;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=1;
+   return res;
+}
+
+static OPUS_INLINE short MULT16_16_P13(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res += 4096;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res >>= 13;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=4;
+   return res;
+}
+static OPUS_INLINE short MULT16_16_P14(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res += 8192;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res >>= 14;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=4;
+   return res;
+}
+static OPUS_INLINE short MULT16_16_P15(int a, int b)
+{
+   opus_int64 res;
+   if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = ((opus_int64)a)*b;
+   res += 16384;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res >>= 15;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=2;
+   return res;
+}
+
+#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
+
+static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+   opus_int64 res;
+   if (b==0)
+   {
+      fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+      return 0;
+   }
+   if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
+   {
+      fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a/b;
+   if (!VERIFY_SHORT(res))
+   {
+      fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
+      if (res>32767)
+         res = 32767;
+      if (res<-32768)
+         res = -32768;
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=35;
+   return res;
+}
+
+#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+   opus_int64 res;
+   if (b==0)
+   {
+      fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+      return 0;
+   }
+
+   if (!VERIFY_INT(a) || !VERIFY_INT(b))
+   {
+      fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   res = a/b;
+   if (!VERIFY_INT(res))
+   {
+      fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+      celt_assert(0);
+#endif
+   }
+   celt_mips+=70;
+   return res;
+}
+
+static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
+{
+   x = PSHR32(x, SIG_SHIFT);
+   x = MAX32(x, -32768);
+   x = MIN32(x, 32767);
+   return EXTRACT16(x);
+}
+#define SIG2WORD16(x) (SIG2WORD16_generic(x))
+
+
+#undef PRINT_MIPS
+#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", (unsigned long long)celt_mips);} while (0);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_generic.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/fixed_generic.h
new file mode 100644 (file)
index 0000000..ee9ea18
--- /dev/null
@@ -0,0 +1,218 @@
+/* Copyright (C) 2007-2009 Xiph.Org Foundation
+   Copyright (C) 2003-2008 Jean-Marc Valin
+   Copyright (C) 2007-2008 CSIRO */
+/**
+   @file fixed_generic.h
+   @brief Generic fixed-point operations
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_GENERIC_H
+#define FIXED_GENERIC_H
+
+/** Multiply a 16-bit signed value by a 16-bit unsigned value. The result is a 32-bit signed value */
+#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
+
+/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_Q16(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),16))
+#else
+#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
+#endif
+
+/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_P16(a,b) ((opus_val32)PSHR((opus_int64)((opus_val16)(a))*(b),16))
+#else
+#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
+#endif
+
+/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_Q15(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),15))
+#else
+#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
+#endif
+
+/** 32x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q16(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),16))
+#else
+#define MULT32_32_Q16(a,b) (ADD32(ADD32(ADD32((opus_val32)(SHR32(((opus_uint32)((a)&0x0000ffff)*(opus_uint32)((b)&0x0000ffff)),16)), MULT16_16SU(SHR32(a,16),((b)&0x0000ffff))), MULT16_16SU(SHR32(b,16),((a)&0x0000ffff))), SHL32(MULT16_16(SHR32(a,16),SHR32(b,16)),16)))
+#endif
+
+/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q31(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),31))
+#else
+#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15))
+#endif
+
+/** 32x32 multiplication, followed by a 31-bit shift right (with rounding). Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_P31(a,b) ((opus_val32)SHR(1073741824+(opus_int64)(a)*(opus_int64)(b),31))
+#define MULT32_32_P31_ovflw(a,b) MULT32_32_P31(a,b)
+#else
+#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b))
+#define MULT32_32_P31(a,b) ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#endif
+
+/** 32x32 multiplication, followed by a 32-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q32(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),32))
+#else
+#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
+#endif
+
+/** Compile-time conversion of float constant to 16-bit value */
+#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
+
+/** Compile-time conversion of float constant to 32-bit value */
+#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_int64)1)<<(bits))))
+
+/** Compile-time conversion of float constant to log gain value */
+#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
+
+/** Compile-time conversion of float constant to DB_SHIFT log gain value */
+#define GCONST(x) GCONST2((x),DB_SHIFT)
+
+/** Negate a 16-bit value */
+#define NEG16(x) (-(x))
+/** Negate a 32-bit value */
+#define NEG32(x) (-(x))
+
+/** Change a 32-bit value into a 16-bit value. The value is assumed to fit in 16-bit, otherwise the result is undefined */
+#define EXTRACT16(x) ((opus_val16)(x))
+/** Change a 16-bit value into a 32-bit value */
+#define EXTEND32(x) ((opus_val32)(x))
+
+/** Arithmetic shift-right of a 16-bit value */
+#define SHR16(a,shift) ((a) >> (shift))
+/** Arithmetic shift-left of a 16-bit value */
+#define SHL16(a,shift) ((opus_int16)((opus_uint16)(a)<<(shift)))
+/** Arithmetic shift-right of a 32-bit value */
+#define SHR32(a,shift) ((a) >> (shift))
+/** Arithmetic shift-left of a 32-bit value */
+#define SHL32(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
+
+/** 32-bit arithmetic shift right with rounding-to-nearest instead of rounding down */
+#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+/** 32-bit arithmetic shift right where the argument can be negative */
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+
+/** Arithmetic shift-right of a 64-bit value */
+#define SHR64(a,shift) ((a) >> (shift))
+
+/** "RAW" macros, should not be used outside of this header file */
+#define SHR(a,shift) ((a) >> (shift))
+#define SHL(a,shift) SHL32(a,shift)
+#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+#define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x)))
+
+/** Shift by a and round-to-nearest 32-bit value. Result is a 16-bit value */
+#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
+/** Shift by a and round-to-nearest 32-bit value. Result is a saturated 16-bit value */
+#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
+
+/** Divide by two */
+#define HALF16(x)  (SHR16(x,1))
+#define HALF32(x)  (SHR32(x,1))
+
+/** Add two 16-bit values */
+#define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b)))
+/** Subtract two 16-bit values */
+#define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b))
+/** Add two 32-bit values */
+#define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b))
+/** Subtract two 32-bit values */
+#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
+
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) SHL32(a,shift)
+/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
+#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
+
+/** 16x16 multiplication where the result fits in 16 bits */
+#define MULT16_16_16(a,b)     ((((opus_val16)(a))*((opus_val16)(b))))
+
+/** 32x32 multiplication where the result fits in 32 bits */
+#define MULT32_32_32(a,b)     ((((opus_val32)(a))*((opus_val32)(b))))
+
+/* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */
+/** 16x16 multiplication where the result fits in 32 bits */
+#define MULT16_16(a,b)     (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b)))
+
+/** 16x16 multiply-add where the result fits in 32 bits */
+#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
+/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
+    b must fit in 31 bits.
+    Result fits in 32 bits. */
+#define MAC16_32_Q15(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+
+/** 16x32 multiplication, followed by a 16-bit shift right and 32-bit add.
+    Results fits in 32 bits */
+#define MAC16_32_Q16(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)))
+
+#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
+#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
+#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
+
+#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
+#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
+#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
+
+/** Divide a 32-bit value by a 16-bit value. Result fits in 16 bits */
+#define DIV32_16(a,b) ((opus_val16)(((opus_val32)(a))/((opus_val16)(b))))
+
+/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */
+#define DIV32(a,b) (((opus_val32)(a))/((opus_val32)(b)))
+
+#if defined(__mips)
+#include "mips/fixed_generic_mipsr1.h"
+#endif
+
+static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
+{
+   x = PSHR32(x, SIG_SHIFT);
+   x = MAX32(x, -32768);
+   x = MIN32(x, 32767);
+   return EXTRACT16(x);
+}
+#define SIG2WORD16(x) (SIG2WORD16_generic(x))
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/float_cast.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/float_cast.h
new file mode 100644 (file)
index 0000000..120a536
--- /dev/null
@@ -0,0 +1,176 @@
+/* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* Version 1.1 */
+
+#ifndef FLOAT_CAST_H
+#define FLOAT_CAST_H
+
+
+#include "arch.h"
+
+/*============================================================================
+**      On Intel Pentium processors (especially PIII and probably P4), converting
+**      from float to int is very slow. To meet the C specs, the code produced by
+**      most C compilers targeting Pentium needs to change the FPU rounding mode
+**      before the float to int conversion is performed.
+**
+**      Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
+**      is this flushing of the pipeline which is so slow.
+**
+**      Fortunately the ISO C99 specifications define the functions lrint, lrintf,
+**      llrint and llrintf which fix this problem as a side effect.
+**
+**      On Unix-like systems, the configure process should have detected the
+**      presence of these functions. If they weren't found we have to replace them
+**      here with a standard C cast.
+*/
+
+/*
+**      The C99 prototypes for lrint and lrintf are as follows:
+**
+**              long int lrintf (float x) ;
+**              long int lrint  (double x) ;
+*/
+
+/*      The presence of the required functions are detected during the configure
+**      process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
+**      the config.h file.
+*/
+
+/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
+#if defined(__GNUC__) && defined(__SSE__)
+
+#include <xmmintrin.h>
+static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
+
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
+
+        #include <xmmintrin.h>
+        static OPUS_INLINE opus_int32 float2int(float value)
+        {
+                /* _mm_load_ss will generate same code as _mm_set_ss
+                ** in _MSC_VER >= 1914 /02 so keep __mm_load__ss
+                ** for backward compatibility.
+                */
+                return _mm_cvtss_si32(_mm_load_ss(&value));
+        }
+
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
+
+        #include <math.h>
+
+        /*      Win32 doesn't seem to have these functions.
+        **      Therefore implement OPUS_INLINE versions of these functions here.
+        */
+
+        static OPUS_INLINE opus_int32
+        float2int (float flt)
+        {       int intgr;
+
+                _asm
+                {       fld flt
+                        fistp intgr
+                } ;
+
+                return intgr ;
+        }
+#elif defined(__aarch64__)
+
+        #include <arm_neon.h>
+        static OPUS_INLINE opus_int32 float2int(float flt)
+        {
+                return vcvtns_s32_f32(flt);
+        }
+
+#elif defined(HAVE_LRINTF) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/*      These defines enable functionality introduced with the 1999 ISO C
+**      standard. They must be defined before the inclusion of math.h to
+**      engage them. If optimisation is enabled, these functions will be
+**      inlined. With optimisation switched off, you have to link in the
+**      maths library using -lm.
+*/
+
+#define _ISOC9X_SOURCE 1
+#define _ISOC99_SOURCE 1
+
+#define __USE_ISOC9X 1
+#define __USE_ISOC99 1
+
+#include <math.h>
+#define float2int(x) lrintf(x)
+
+#elif defined(HAVE_LRINT) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+#define _ISOC9X_SOURCE 1
+#define _ISOC99_SOURCE 1
+
+#define __USE_ISOC9X 1
+#define __USE_ISOC99 1
+
+#include <math.h>
+#define float2int(x) lrint(x)
+
+#else
+
+#if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
+        /* supported by gcc in C99 mode, but not by all other compilers */
+        #warning "Don't have the functions lrint() and lrintf ()."
+        #warning "Replacing these functions with a standard C cast."
+#endif /* __STDC_VERSION__ >= 199901L */
+        #include <math.h>
+        #define float2int(flt) ((int)(floor(.5+flt)))
+#endif
+
+#ifndef DISABLE_FLOAT_API
+static OPUS_INLINE opus_int16 FLOAT2INT16(float x)
+{
+   x = x*CELT_SIG_SCALE;
+   x = MAX32(x, -32768);
+   x = MIN32(x, 32767);
+   return (opus_int16)float2int(x);
+}
+
+static OPUS_INLINE opus_int32 FLOAT2INT24(float x)
+{
+   x = x*(CELT_SIG_SCALE*256.f);
+   x = MAX32(x, -16777216);
+   x = MIN32(x, 16777216);
+   return float2int(x);
+}
+#ifdef FIXED_POINT
+static OPUS_INLINE opus_int32 FLOAT2SIG(float x)
+{
+   x = x*((opus_int32)32768<<SIG_SHIFT);
+   x = MAX32(x, -(65536<<SIG_SHIFT));
+   x = MIN32(x, 65536<<SIG_SHIFT);
+   return float2int(x);
+}
+#endif
+#endif /* DISABLE_FLOAT_API */
+
+#endif /* FLOAT_CAST_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.c
new file mode 100644 (file)
index 0000000..24400e8
--- /dev/null
@@ -0,0 +1,650 @@
+/*Copyright (c) 2003-2004, Mark Borgerding
+  Lots of modifications by Jean-Marc Valin
+  Copyright (c) 2005-2007, Xiph.Org Foundation
+  Copyright (c) 2008,      Xiph.Org Foundation, CSIRO
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.*/
+
+/* This code is originally from Mark Borgerding's KISS-FFT but has been
+   heavily modified to better suit Opus */
+
+#ifndef SKIP_CONFIG_H
+#  ifdef HAVE_CONFIG_H
+#    include "config.h"
+#  endif
+#endif
+
+#include "_kiss_fft_guts.h"
+#include "arch.h"
+#include "os_support.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+/* The guts header contains all the multiplication and addition macros that are defined for
+   complex numbers.  It also declares the kf_ internal functions.
+*/
+
+static void kf_bfly2(
+                     kiss_fft_cpx * Fout,
+                     int m,
+                     int N
+                    )
+{
+   kiss_fft_cpx * Fout2;
+   int i;
+   (void)m;
+#ifdef CUSTOM_MODES
+   if (m==1)
+   {
+      celt_assert(m==1);
+      for (i=0;i<N;i++)
+      {
+         kiss_fft_cpx t;
+         Fout2 = Fout + 1;
+         t = *Fout2;
+         C_SUB( *Fout2 ,  *Fout , t );
+         C_ADDTO( *Fout ,  t );
+         Fout += 2;
+      }
+   } else
+#endif
+   {
+      celt_coef tw;
+      tw = QCONST32(0.7071067812f, COEF_SHIFT-1);
+      /* We know that m==4 here because the radix-2 is just after a radix-4 */
+      celt_assert(m==4);
+      for (i=0;i<N;i++)
+      {
+         kiss_fft_cpx t;
+         Fout2 = Fout + 4;
+         t = Fout2[0];
+         C_SUB( Fout2[0] ,  Fout[0] , t );
+         C_ADDTO( Fout[0] ,  t );
+
+         t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
+         t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
+         C_SUB( Fout2[1] ,  Fout[1] , t );
+         C_ADDTO( Fout[1] ,  t );
+
+         t.r = Fout2[2].i;
+         t.i = NEG32_ovflw(Fout2[2].r);
+         C_SUB( Fout2[2] ,  Fout[2] , t );
+         C_ADDTO( Fout[2] ,  t );
+
+         t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
+         t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
+         C_SUB( Fout2[3] ,  Fout[3] , t );
+         C_ADDTO( Fout[3] ,  t );
+         Fout += 8;
+      }
+   }
+}
+
+static void kf_bfly4(
+                     kiss_fft_cpx * Fout,
+                     const size_t fstride,
+                     const kiss_fft_state *st,
+                     int m,
+                     int N,
+                     int mm
+                    )
+{
+   int i;
+
+   if (m==1)
+   {
+      /* Degenerate case where all the twiddles are 1. */
+      for (i=0;i<N;i++)
+      {
+         kiss_fft_cpx scratch0, scratch1;
+
+         C_SUB( scratch0 , *Fout, Fout[2] );
+         C_ADDTO(*Fout, Fout[2]);
+         C_ADD( scratch1 , Fout[1] , Fout[3] );
+         C_SUB( Fout[2], *Fout, scratch1 );
+         C_ADDTO( *Fout , scratch1 );
+         C_SUB( scratch1 , Fout[1] , Fout[3] );
+
+         Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
+         Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
+         Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
+         Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
+         Fout+=4;
+      }
+   } else {
+      int j;
+      kiss_fft_cpx scratch[6];
+      const kiss_twiddle_cpx *tw1,*tw2,*tw3;
+      const int m2=2*m;
+      const int m3=3*m;
+      kiss_fft_cpx * Fout_beg = Fout;
+      for (i=0;i<N;i++)
+      {
+         Fout = Fout_beg + i*mm;
+         tw3 = tw2 = tw1 = st->twiddles;
+         /* m is guaranteed to be a multiple of 4. */
+         for (j=0;j<m;j++)
+         {
+            C_MUL(scratch[0],Fout[m] , *tw1 );
+            C_MUL(scratch[1],Fout[m2] , *tw2 );
+            C_MUL(scratch[2],Fout[m3] , *tw3 );
+
+            C_SUB( scratch[5] , *Fout, scratch[1] );
+            C_ADDTO(*Fout, scratch[1]);
+            C_ADD( scratch[3] , scratch[0] , scratch[2] );
+            C_SUB( scratch[4] , scratch[0] , scratch[2] );
+            C_SUB( Fout[m2], *Fout, scratch[3] );
+            tw1 += fstride;
+            tw2 += fstride*2;
+            tw3 += fstride*3;
+            C_ADDTO( *Fout , scratch[3] );
+
+            Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
+            Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
+            ++Fout;
+         }
+      }
+   }
+}
+
+
+#ifndef RADIX_TWO_ONLY
+
+static void kf_bfly3(
+                     kiss_fft_cpx * Fout,
+                     const size_t fstride,
+                     const kiss_fft_state *st,
+                     int m,
+                     int N,
+                     int mm
+                    )
+{
+   int i;
+   size_t k;
+   const size_t m2 = 2*m;
+   const kiss_twiddle_cpx *tw1,*tw2;
+   kiss_fft_cpx scratch[5];
+   kiss_twiddle_cpx epi3;
+
+   kiss_fft_cpx * Fout_beg = Fout;
+#ifdef FIXED_POINT
+   /*epi3.r = -16384;*/ /* Unused */
+   epi3.i = -QCONST32(0.86602540f, COEF_SHIFT-1);
+#else
+   epi3 = st->twiddles[fstride*m];
+#endif
+   for (i=0;i<N;i++)
+   {
+      Fout = Fout_beg + i*mm;
+      tw1=tw2=st->twiddles;
+      /* For non-custom modes, m is guaranteed to be a multiple of 4. */
+      k=m;
+      do {
+
+         C_MUL(scratch[1],Fout[m] , *tw1);
+         C_MUL(scratch[2],Fout[m2] , *tw2);
+
+         C_ADD(scratch[3],scratch[1],scratch[2]);
+         C_SUB(scratch[0],scratch[1],scratch[2]);
+         tw1 += fstride;
+         tw2 += fstride*2;
+
+         Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
+         Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
+
+         C_MULBYSCALAR( scratch[0] , epi3.i );
+
+         C_ADDTO(*Fout,scratch[3]);
+
+         Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
+
+         Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
+
+         ++Fout;
+      } while(--k);
+   }
+}
+
+
+#ifndef OVERRIDE_kf_bfly5
+static void kf_bfly5(
+                     kiss_fft_cpx * Fout,
+                     const size_t fstride,
+                     const kiss_fft_state *st,
+                     int m,
+                     int N,
+                     int mm
+                    )
+{
+   kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
+   int i, u;
+   kiss_fft_cpx scratch[13];
+   const kiss_twiddle_cpx *tw;
+   kiss_twiddle_cpx ya,yb;
+   kiss_fft_cpx * Fout_beg = Fout;
+
+#ifdef FIXED_POINT
+   ya.r = QCONST32(0.30901699f, COEF_SHIFT-1);
+   ya.i = -QCONST32(0.95105652f, COEF_SHIFT-1);
+   yb.r = -QCONST32(0.80901699f, COEF_SHIFT-1);
+   yb.i = -QCONST32(0.58778525f, COEF_SHIFT-1);
+#else
+   ya = st->twiddles[fstride*m];
+   yb = st->twiddles[fstride*2*m];
+#endif
+   tw=st->twiddles;
+
+   for (i=0;i<N;i++)
+   {
+      Fout = Fout_beg + i*mm;
+      Fout0=Fout;
+      Fout1=Fout0+m;
+      Fout2=Fout0+2*m;
+      Fout3=Fout0+3*m;
+      Fout4=Fout0+4*m;
+
+      /* For non-custom modes, m is guaranteed to be a multiple of 4. */
+      for ( u=0; u<m; ++u ) {
+         scratch[0] = *Fout0;
+
+         C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
+         C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
+         C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
+         C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
+
+         C_ADD( scratch[7],scratch[1],scratch[4]);
+         C_SUB( scratch[10],scratch[1],scratch[4]);
+         C_ADD( scratch[8],scratch[2],scratch[3]);
+         C_SUB( scratch[9],scratch[2],scratch[3]);
+
+         Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
+         Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
+
+         scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
+         scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
+
+         scratch[6].r =  ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
+         scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
+
+         C_SUB(*Fout1,scratch[5],scratch[6]);
+         C_ADD(*Fout4,scratch[5],scratch[6]);
+
+         scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
+         scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
+         scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
+         scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
+
+         C_ADD(*Fout2,scratch[11],scratch[12]);
+         C_SUB(*Fout3,scratch[11],scratch[12]);
+
+         ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
+      }
+   }
+}
+#endif /* OVERRIDE_kf_bfly5 */
+
+
+#endif
+
+
+#ifdef CUSTOM_MODES
+
+static
+void compute_bitrev_table(
+         int Fout,
+         opus_int16 *f,
+         const size_t fstride,
+         int in_stride,
+         opus_int16 * factors,
+         const kiss_fft_state *st
+            )
+{
+   const int p=*factors++; /* the radix  */
+   const int m=*factors++; /* stage's fft length/p */
+
+    /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
+   if (m==1)
+   {
+      int j;
+      for (j=0;j<p;j++)
+      {
+         *f = Fout+j;
+         f += fstride*in_stride;
+      }
+   } else {
+      int j;
+      for (j=0;j<p;j++)
+      {
+         compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
+         f += fstride*in_stride;
+         Fout += m;
+      }
+   }
+}
+
+/*  facbuf is populated by p1,m1,p2,m2, ...
+    where
+    p[i] * m[i] = m[i-1]
+    m0 = n                  */
+static
+int kf_factor(int n,opus_int16 * facbuf)
+{
+    int p=4;
+    int i;
+    int stages=0;
+    int nbak = n;
+
+    /*factor out powers of 4, powers of 2, then any remaining primes */
+    do {
+        while (n % p) {
+            switch (p) {
+                case 4: p = 2; break;
+                case 2: p = 3; break;
+                default: p += 2; break;
+            }
+            if (p>32000 || (opus_int32)p*(opus_int32)p > n)
+                p = n;          /* no more factors, skip to end */
+        }
+        n /= p;
+#ifdef RADIX_TWO_ONLY
+        if (p!=2 && p != 4)
+#else
+        if (p>5)
+#endif
+        {
+           return 0;
+        }
+        facbuf[2*stages] = p;
+        if (p==2 && stages > 1)
+        {
+           facbuf[2*stages] = 4;
+           facbuf[2] = 2;
+        }
+        stages++;
+    } while (n > 1);
+    n = nbak;
+    /* Reverse the order to get the radix 4 at the end, so we can use the
+       fast degenerate case. It turns out that reversing the order also
+       improves the noise behaviour. */
+    for (i=0;i<stages/2;i++)
+    {
+       int tmp;
+       tmp = facbuf[2*i];
+       facbuf[2*i] = facbuf[2*(stages-i-1)];
+       facbuf[2*(stages-i-1)] = tmp;
+    }
+    for (i=0;i<stages;i++)
+    {
+        n /= facbuf[2*i];
+        facbuf[2*i+1] = n;
+    }
+    return 1;
+}
+
+static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
+{
+   int i;
+#ifdef FIXED_POINT
+   for (i=0;i<nfft;++i) {
+      opus_val32 phase = -i;
+#ifdef ENABLE_QEXT
+      twiddles[i].r = (int)MIN32(2147483647, floor(.5+2147483648*cos((2*M_PI/nfft)*phase)));
+      twiddles[i].i = (int)MIN32(2147483647, floor(.5+2147483648*sin((2*M_PI/nfft)*phase)));
+#else
+      kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
+#endif
+   }
+#else
+   for (i=0;i<nfft;++i) {
+      const double pi=3.14159265358979323846264338327;
+      double phase = ( -2*pi /nfft ) * i;
+      kf_cexp(twiddles+i, phase );
+   }
+#endif
+}
+
+int opus_fft_alloc_arch_c(kiss_fft_state *st) {
+   (void)st;
+   return 0;
+}
+
+/*
+ *
+ * Allocates all necessary storage space for the fft and ifft.
+ * The return value is a contiguous block of memory.  As such,
+ * It can be freed with free().
+ * */
+kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
+                                        const kiss_fft_state *base, int arch)
+{
+    kiss_fft_state *st=NULL;
+    size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
+
+    if ( lenmem==NULL ) {
+        st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
+    }else{
+        if (mem != NULL && *lenmem >= memneeded)
+            st = (kiss_fft_state*)mem;
+        *lenmem = memneeded;
+    }
+    if (st) {
+        opus_int16 *bitrev;
+        kiss_twiddle_cpx *twiddles;
+
+        st->nfft=nfft;
+#ifdef FIXED_POINT
+        st->scale_shift = celt_ilog2(st->nfft);
+# ifdef ENABLE_QEXT
+        if (st->nfft == 1<<st->scale_shift)
+           st->scale = QCONST32(1.0f, 30);
+        else
+           st->scale = (((opus_int64)1073741824<<st->scale_shift)+st->nfft/2)/st->nfft;
+# else
+        if (st->nfft == 1<<st->scale_shift)
+           st->scale = Q15ONE;
+        else
+           st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift);
+# endif
+#else
+        st->scale = 1.f/nfft;
+#endif
+        if (base != NULL)
+        {
+           st->twiddles = base->twiddles;
+           st->shift = 0;
+           while (st->shift < 32 && nfft<<st->shift != base->nfft)
+              st->shift++;
+           if (st->shift>=32)
+              goto fail;
+        } else {
+           st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
+           compute_twiddles(twiddles, nfft);
+           st->shift = -1;
+        }
+        if (!kf_factor(nfft,st->factors))
+        {
+           goto fail;
+        }
+
+        /* bitrev */
+        st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
+        if (st->bitrev==NULL)
+            goto fail;
+        compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
+
+        /* Initialize architecture specific fft parameters */
+        if (opus_fft_alloc_arch(st, arch))
+            goto fail;
+    }
+    return st;
+fail:
+    opus_fft_free(st, arch);
+    return NULL;
+}
+
+kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch)
+{
+   return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
+}
+
+void opus_fft_free_arch_c(kiss_fft_state *st) {
+   (void)st;
+}
+
+void opus_fft_free(const kiss_fft_state *cfg, int arch)
+{
+   if (cfg)
+   {
+      opus_fft_free_arch((kiss_fft_state *)cfg, arch);
+      opus_free((opus_int16*)cfg->bitrev);
+      if (cfg->shift < 0)
+         opus_free((kiss_twiddle_cpx*)cfg->twiddles);
+      opus_free((kiss_fft_state*)cfg);
+   }
+}
+
+#endif /* CUSTOM_MODES */
+
+#ifdef FIXED_POINT
+#ifndef OVERRIDE_fft_downshift
+static void fft_downshift(kiss_fft_cpx *x, int N, int *total, int step) {
+   int shift;
+   shift = IMIN(step, *total);
+   *total -= shift;
+   if (shift == 1) {
+      int i;
+      for (i=0;i<N;i++) {
+         x[i].r = SHR32(x[i].r, 1);
+         x[i].i = SHR32(x[i].i, 1);
+      }
+   } else if (shift>0) {
+      int i;
+      for (i=0;i<N;i++) {
+         x[i].r = PSHR32(x[i].r, shift);
+         x[i].i = PSHR32(x[i].i, shift);
+      }
+   }
+}
+#endif /* OVERRIDE_fft_downshift */
+#else
+#define fft_downshift(x, N, total, step)
+#endif
+
+void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift))
+{
+    int m2, m;
+    int p;
+    int L;
+    int fstride[MAXFACTORS];
+    int i;
+    int shift;
+
+    /* st->shift can be -1 */
+    shift = st->shift>0 ? st->shift : 0;
+
+    fstride[0] = 1;
+    L=0;
+    do {
+       p = st->factors[2*L];
+       m = st->factors[2*L+1];
+       fstride[L+1] = fstride[L]*p;
+       L++;
+    } while(m!=1);
+    m = st->factors[2*L-1];
+    for (i=L-1;i>=0;i--)
+    {
+       if (i!=0)
+          m2 = st->factors[2*i-1];
+       else
+          m2 = 1;
+       switch (st->factors[2*i])
+       {
+       case 2:
+          fft_downshift(fout, st->nfft, &downshift, 1);
+          kf_bfly2(fout, m, fstride[i]);
+          break;
+       case 4:
+          fft_downshift(fout, st->nfft, &downshift, 2);
+          kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+          break;
+ #ifndef RADIX_TWO_ONLY
+       case 3:
+          fft_downshift(fout, st->nfft, &downshift, 2);
+          kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+          break;
+       case 5:
+          fft_downshift(fout, st->nfft, &downshift, 3);
+          kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+          break;
+ #endif
+       }
+       m = m2;
+    }
+    fft_downshift(fout, st->nfft, &downshift, downshift);
+}
+
+void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+{
+   int i;
+   celt_coef scale;
+#ifdef FIXED_POINT
+   /* Allows us to scale with MULT16_32_Q16(), which is faster than
+      MULT16_32_Q15() on ARM. */
+   int scale_shift = st->scale_shift-1;
+#endif
+   scale = st->scale;
+
+   celt_assert2 (fin != fout, "In-place FFT not supported");
+   /* Bit-reverse the input */
+   for (i=0;i<st->nfft;i++)
+   {
+      kiss_fft_cpx x = fin[i];
+      fout[st->bitrev[i]].r = S_MUL2(x.r, scale);
+      fout[st->bitrev[i]].i = S_MUL2(x.i, scale);
+   }
+   opus_fft_impl(st, fout ARG_FIXED(scale_shift));
+}
+
+
+void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+{
+   int i;
+   celt_assert2 (fin != fout, "In-place FFT not supported");
+   /* Bit-reverse the input */
+   for (i=0;i<st->nfft;i++)
+      fout[st->bitrev[i]] = fin[i];
+   for (i=0;i<st->nfft;i++)
+      fout[i].i = -fout[i].i;
+   opus_fft_impl(st, fout ARG_FIXED(0));
+   for (i=0;i<st->nfft;i++)
+      fout[i].i = -fout[i].i;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/kiss_fft.h
new file mode 100644 (file)
index 0000000..20eb0b2
--- /dev/null
@@ -0,0 +1,209 @@
+/*Copyright (c) 2003-2004, Mark Borgerding
+  Lots of modifications by Jean-Marc Valin
+  Copyright (c) 2005-2007, Xiph.Org Foundation
+  Copyright (c) 2008,      Xiph.Org Foundation, CSIRO
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.*/
+
+#ifndef KISS_FFT_H
+#define KISS_FFT_H
+
+#include <stdlib.h>
+#include <math.h>
+#include "arch.h"
+#include "cpu_support.h"
+
+#ifdef USE_SIMD
+# include <xmmintrin.h>
+# define kiss_fft_scalar __m128
+#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
+#else
+#define KISS_FFT_MALLOC opus_alloc
+#endif
+
+#ifdef FIXED_POINT
+#include "arch.h"
+
+#  define kiss_fft_scalar opus_int32
+#  ifdef ENABLE_QEXT
+#   define COEF_SHIFT 32
+#  else
+#   define COEF_SHIFT 16
+#  endif
+
+#  define kiss_twiddle_scalar celt_coef
+
+/* Some 32-bit CPUs would load/store a kiss_twiddle_cpx with a single memory
+ * access, and could benefit from additional alignment.
+ */
+#  define KISS_TWIDDLE_CPX_ALIGNMENT (sizeof(opus_int32))
+
+#else
+
+# ifndef kiss_fft_scalar
+/*  default is float */
+#   define kiss_fft_scalar float
+#   define kiss_twiddle_scalar float
+#   define KF_SUFFIX _celt_single
+# endif
+#endif
+
+#if defined(__GNUC__) && defined(KISS_TWIDDLE_CPX_ALIGNMENT)
+#define KISS_TWIDDLE_CPX_ALIGNED __attribute__((aligned(KISS_TWIDDLE_CPX_ALIGNMENT)))
+#else
+#define KISS_TWIDDLE_CPX_ALIGNED
+#endif
+
+typedef struct {
+    kiss_fft_scalar r;
+    kiss_fft_scalar i;
+}kiss_fft_cpx;
+
+typedef struct {
+   kiss_twiddle_scalar r;
+   kiss_twiddle_scalar i;
+} KISS_TWIDDLE_CPX_ALIGNED kiss_twiddle_cpx;
+
+#define MAXFACTORS 8
+/* e.g. an fft of length 128 has 4 factors
+ as far as kissfft is concerned
+ 4*4*4*2
+ */
+
+typedef struct arch_fft_state{
+   int is_supported;
+   void *priv;
+} arch_fft_state;
+
+typedef struct kiss_fft_state{
+    int nfft;
+    celt_coef scale;
+#ifdef FIXED_POINT
+    int scale_shift;
+#endif
+    int shift;
+    opus_int16 factors[2*MAXFACTORS];
+    const opus_int16 *bitrev;
+    const kiss_twiddle_cpx *twiddles;
+    arch_fft_state *arch_fft;
+} kiss_fft_state;
+
+#if defined(HAVE_ARM_NE10)
+#include "arm/fft_arm.h"
+#endif
+
+/*typedef struct kiss_fft_state* kiss_fft_cfg;*/
+
+/**
+ *  opus_fft_alloc
+ *
+ *  Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
+ *
+ *  typical usage:      kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL);
+ *
+ *  The return value from fft_alloc is a cfg buffer used internally
+ *  by the fft routine or NULL.
+ *
+ *  If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc.
+ *  The returned value should be free()d when done to avoid memory leaks.
+ *
+ *  The state can be placed in a user supplied buffer 'mem':
+ *  If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
+ *      then the function places the cfg in mem and the size used in *lenmem
+ *      and returns mem.
+ *
+ *  If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
+ *      then the function returns NULL and places the minimum cfg
+ *      buffer size in *lenmem.
+ * */
+
+kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base, int arch);
+
+kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch);
+
+/**
+ * opus_fft(cfg,in_out_buf)
+ *
+ * Perform an FFT on a complex input buffer.
+ * for a forward FFT,
+ * fin should be  f[0] , f[1] , ... ,f[nfft-1]
+ * fout will be   F[0] , F[1] , ... ,F[nfft-1]
+ * Note that each element is complex and can be accessed like
+    f[k].r and f[k].i
+ * */
+void opus_fft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
+void opus_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
+
+void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift));
+void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
+
+void opus_fft_free(const kiss_fft_state *cfg, int arch);
+
+
+void opus_fft_free_arch_c(kiss_fft_state *st);
+int opus_fft_alloc_arch_c(kiss_fft_state *st);
+
+#if !defined(OVERRIDE_OPUS_FFT)
+/* Is run-time CPU detection enabled on this platform? */
+#if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10))
+
+extern int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(
+ kiss_fft_state *st);
+
+#define opus_fft_alloc_arch(_st, arch) \
+         ((*OPUS_FFT_ALLOC_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
+
+extern void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(
+ kiss_fft_state *st);
+#define opus_fft_free_arch(_st, arch) \
+         ((*OPUS_FFT_FREE_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
+
+extern void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
+ const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
+#define opus_fft(_cfg, _fin, _fout, arch) \
+   ((*OPUS_FFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
+
+extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
+ const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
+#define opus_ifft(_cfg, _fin, _fout, arch) \
+   ((*OPUS_IFFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
+
+#else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
+
+#define opus_fft_alloc_arch(_st, arch) \
+         ((void)(arch), opus_fft_alloc_arch_c(_st))
+
+#define opus_fft_free_arch(_st, arch) \
+         ((void)(arch), opus_fft_free_arch_c(_st))
+
+#define opus_fft(_cfg, _fin, _fout, arch) \
+         ((void)(arch), opus_fft_c(_cfg, _fin, _fout))
+
+#define opus_ifft(_cfg, _fin, _fout, arch) \
+         ((void)(arch), opus_ifft_c(_cfg, _fin, _fout))
+
+#endif /* end if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
+#endif /* end if !defined(OVERRIDE_OPUS_FFT) */
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.c
new file mode 100644 (file)
index 0000000..2180966
--- /dev/null
@@ -0,0 +1,235 @@
+/* Copyright (c) 2007 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "laplace.h"
+#include "mathops.h"
+
+/* The minimum probability of an energy delta (out of 32768). */
+#define LAPLACE_LOG_MINP (0)
+#define LAPLACE_MINP (1<<LAPLACE_LOG_MINP)
+/* The minimum number of guaranteed representable energy deltas (in one
+    direction). */
+#define LAPLACE_NMIN (16)
+
+/* When called, decay is positive and at most 11456. */
+static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
+{
+   unsigned ft;
+   ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
+   return ft*(opus_int32)(16384-decay)>>15;
+}
+
+void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
+{
+   unsigned fl;
+   int val = *value;
+   fl = 0;
+   if (val)
+   {
+      int s;
+      int i;
+      s = -(val<0);
+      val = (val+s)^s;
+      fl = fs;
+      fs = ec_laplace_get_freq1(fs, decay);
+      /* Search the decaying part of the PDF.*/
+      for (i=1; fs > 0 && i < val; i++)
+      {
+         fs *= 2;
+         fl += fs+2*LAPLACE_MINP;
+         fs = (fs*(opus_int32)decay)>>15;
+      }
+      /* Everything beyond that has probability LAPLACE_MINP. */
+      if (!fs)
+      {
+         int di;
+         int ndi_max;
+         ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
+         ndi_max = (ndi_max-s)>>1;
+         di = IMIN(val - i, ndi_max - 1);
+         fl += (2*di+1+s)*LAPLACE_MINP;
+         fs = IMIN(LAPLACE_MINP, 32768-fl);
+         *value = (i+di+s)^s;
+      }
+      else
+      {
+         fs += LAPLACE_MINP;
+         fl += fs&~s;
+      }
+      celt_assert(fl+fs<=32768);
+      celt_assert(fs>0);
+   }
+   ec_encode_bin(enc, fl, fl+fs, 15);
+}
+
+int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
+{
+   int val=0;
+   unsigned fl;
+   unsigned fm;
+   fm = ec_decode_bin(dec, 15);
+   fl = 0;
+   if (fm >= fs)
+   {
+      val++;
+      fl = fs;
+      fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP;
+      /* Search the decaying part of the PDF.*/
+      while(fs > LAPLACE_MINP && fm >= fl+2*fs)
+      {
+         fs *= 2;
+         fl += fs;
+         fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15;
+         fs += LAPLACE_MINP;
+         val++;
+      }
+      /* Everything beyond that has probability LAPLACE_MINP. */
+      if (fs <= LAPLACE_MINP)
+      {
+         int di;
+         di = (fm-fl)>>(LAPLACE_LOG_MINP+1);
+         val += di;
+         fl += 2*di*LAPLACE_MINP;
+      }
+      if (fm < fl+fs)
+         val = -val;
+      else
+         fl += fs;
+   }
+   celt_assert(fl<32768);
+   celt_assert(fs>0);
+   celt_assert(fl<=fm);
+   celt_assert(fm<IMIN(fl+fs,32768));
+   ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
+   return val;
+}
+
+void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay)
+{
+   int s;
+   opus_uint16 sign_icdf[3];
+   sign_icdf[0] = 32768-p0;
+   sign_icdf[1] = sign_icdf[0]/2;
+   sign_icdf[2] = 0;
+   s = value == 0 ? 0 : (value > 0 ? 1 : 2);
+   ec_enc_icdf16(enc, s, sign_icdf, 15);
+   value = abs(value);
+   if (value)
+   {
+      int i;
+      opus_uint16 icdf[8];
+      icdf[0] = IMAX(7, decay);
+      for (i=1;i<7;i++)
+      {
+         icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
+      }
+      icdf[7] = 0;
+      value--;
+      do {
+         ec_enc_icdf16(enc, IMIN(value, 7), icdf, 15);
+         value -= 7;
+      } while (value >= 0);
+   }
+}
+
+int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay)
+{
+   int s;
+   int value;
+   opus_uint16 sign_icdf[3];
+   sign_icdf[0] = 32768-p0;
+   sign_icdf[1] = sign_icdf[0]/2;
+   sign_icdf[2] = 0;
+   s = ec_dec_icdf16(dec, sign_icdf, 15);
+   if (s==2) s = -1;
+   if (s != 0)
+   {
+      int i;
+      int v;
+      opus_uint16 icdf[8];
+      icdf[0] = IMAX(7, decay);
+      for (i=1;i<7;i++)
+      {
+         icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
+      }
+      icdf[7] = 0;
+      value = 1;
+      do {
+         v = ec_dec_icdf16(dec, icdf, 15);
+         value += v;
+      } while (v == 7);
+      return s*value;
+   } else return 0;
+}
+
+#if 0
+
+#include <stdio.h>
+#define NB_VALS 10
+#define DATA_SIZE 10000
+int main() {
+   ec_enc enc;
+   ec_dec dec;
+   unsigned char *ptr;
+   int i;
+   int decay, p0;
+   int val[NB_VALS] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+   /*for (i=0;i<NB_VALS;i++) {
+      val[i] = -log(rand()/(float)RAND_MAX);
+      if (rand()%2) val[i] = -val[i];
+   }*/
+   p0 = 16000;
+   decay = 16000;
+   ptr = (unsigned char *)malloc(DATA_SIZE);
+   ec_enc_init(&enc,ptr,DATA_SIZE);
+   for (i=0;i<NB_VALS;i++) {
+      printf("%d ", val[i]);
+   }
+   printf("\n");
+   for (i=0;i<NB_VALS;i++) {
+      ec_laplace_encode_p0(&enc, val[i], p0, decay);
+   }
+
+   ec_enc_done(&enc);
+
+   ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
+
+   for (i=0;i<NB_VALS;i++) {
+      val[i] = ec_laplace_decode_p0(&dec, p0, decay);
+   }
+   for (i=0;i<NB_VALS;i++) {
+      printf("%d ", val[i]);
+   }
+   printf("\n");
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/laplace.h
new file mode 100644 (file)
index 0000000..8010ad9
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (c) 2007 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef LAPLACE_H
+#define LAPLACE_H
+
+#include "entenc.h"
+#include "entdec.h"
+
+/** Encode a value that is assumed to be the realisation of a
+    Laplace-distributed random process
+ @param enc Entropy encoder state
+ @param value Value to encode
+ @param fs Probability of 0, multiplied by 32768
+ @param decay Probability of the value +/- 1, multiplied by 16384
+*/
+void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay);
+
+/** Decode a value that is assumed to be the realisation of a
+    Laplace-distributed random process
+ @param dec Entropy decoder state
+ @param fs Probability of 0, multiplied by 32768
+ @param decay Probability of the value +/- 1, multiplied by 16384
+ @return Value decoded
+ */
+int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay);
+
+
+int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay);
+void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.c
new file mode 100644 (file)
index 0000000..dbb3761
--- /dev/null
@@ -0,0 +1,336 @@
+/* Copyright (c) 2002-2008 Jean-Marc Valin
+   Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2024 Arm Limited
+   Written by Jean-Marc Valin */
+/**
+   @file mathops.h
+   @brief Various math functions
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "float_cast.h"
+#include "mathops.h"
+
+/*Compute floor(sqrt(_val)) with exact arithmetic.
+  _val must be greater than 0.
+  This has been tested on all possible 32-bit inputs greater than 0.*/
+unsigned isqrt32(opus_uint32 _val){
+  unsigned b;
+  unsigned g;
+  int      bshift;
+  /*Uses the second method from
+     http://www.azillionmonkeys.com/qed/sqroot.html
+    The main idea is to search for the largest binary digit b such that
+     (g+b)*(g+b) <= _val, and add it to the solution g.*/
+  g=0;
+  bshift=(EC_ILOG(_val)-1)>>1;
+  b=1U<<bshift;
+  do{
+    opus_uint32 t;
+    t=(((opus_uint32)g<<1)+b)<<bshift;
+    if(t<=_val){
+      g+=b;
+      _val-=t;
+    }
+    b>>=1;
+    bshift--;
+  }
+  while(bshift>=0);
+  return g;
+}
+
+#ifdef FIXED_POINT
+
+opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b)
+{
+   opus_val16 rcp;
+   opus_val32 result, rem;
+   int shift = celt_ilog2(b)-29;
+   a = VSHR32(a,shift);
+   b = VSHR32(b,shift);
+   /* 16-bit reciprocal */
+   rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
+   result = MULT16_32_Q15(rcp, a);
+   rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
+   result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
+   return result;
+}
+
+opus_val32 frac_div32(opus_val32 a, opus_val32 b) {
+   opus_val32 result = frac_div32_q29(a,b);
+   if (result >= 536870912)       /*  2^29 */
+      return 2147483647;          /*  2^31 - 1 */
+   else if (result <= -536870912) /* -2^29 */
+      return -2147483647;         /* -2^31 */
+   else
+      return SHL32(result, 2);
+}
+
+/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */
+opus_val16 celt_rsqrt_norm(opus_val32 x)
+{
+   opus_val16 n;
+   opus_val16 r;
+   opus_val16 r2;
+   opus_val16 y;
+   /* Range of n is [-16384,32767] ([-0.5,1) in Q15). */
+   n = x-32768;
+   /* Get a rough initial guess for the root.
+      The optimal minimax quadratic approximation (using relative error) is
+       r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485).
+      Coefficients here, and the final result r, are Q14.*/
+   r = ADD16(23557, MULT16_16_Q15(n, ADD16(-13490, MULT16_16_Q15(n, 6713))));
+   /* We want y = x*r*r-1 in Q15, but x is 32-bit Q16 and r is Q14.
+      We can compute the result from n and r using Q15 multiplies with some
+       adjustment, carefully done to avoid overflow.
+      Range of y is [-1564,1594]. */
+   r2 = MULT16_16_Q15(r, r);
+   y = SHL16(SUB16(ADD16(MULT16_16_Q15(r2, n), r2), 16384), 1);
+   /* Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5).
+      This yields the Q14 reciprocal square root of the Q16 x, with a maximum
+       relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a
+       peak absolute error of 2.26591/16384. */
+   return ADD16(r, MULT16_16_Q15(r, MULT16_16_Q15(y,
+              SUB16(MULT16_16_Q15(y, 12288), 16384))));
+}
+
+/** Reciprocal sqrt approximation in the range [0.25,1) (Q31 in, Q29 out) */
+opus_val32 celt_rsqrt_norm32(opus_val32 x)
+{
+   opus_int32 tmp;
+   /* Use the first-order Newton-Raphson method to refine the root estimate.
+    * r = r * (1.5 - 0.5*x*r*r) */
+   opus_int32 r_q29 = SHL32(celt_rsqrt_norm(SHR32(x, 31-16)), 15);
+   /* Split evaluation in steps to avoid exploding macro expansion. */
+   tmp = MULT32_32_Q31(r_q29, r_q29);
+   tmp = MULT32_32_Q31(1073741824 /* Q31 */, tmp);
+   tmp = MULT32_32_Q31(x, tmp);
+   return SHL32(MULT32_32_Q31(r_q29, SUB32(201326592 /* Q27 */, tmp)), 4);
+}
+
+/** Sqrt approximation (QX input, QX/2 output) */
+opus_val32 celt_sqrt(opus_val32 x)
+{
+   int k;
+   opus_val16 n;
+   opus_val32 rt;
+   /* These coeffs are optimized in fixed-point to minimize both RMS and max error
+      of sqrt(x) over .25<x<1 without exceeding 32767.
+      The RMS error is 3.4e-5 and the max is 8.2e-5. */
+   static const opus_val16 C[6] = {23171, 11574, -2901, 1592, -1002, 336};
+   if (x==0)
+      return 0;
+   else if (x>=1073741824)
+      return 32767;
+   k = (celt_ilog2(x)>>1)-7;
+   x = VSHR32(x, 2*k);
+   n = x-32768;
+   rt = ADD32(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2],
+              MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, ADD16(C[4], MULT16_16_Q15(n, (C[5])))))))))));
+   rt = VSHR32(rt,7-k);
+   return rt;
+}
+
+/* Perform fixed-point arithmetic to approximate the square root. When the input
+ * is in Qx format, the output will be in Q(x/2 + 16) format. */
+opus_val32 celt_sqrt32(opus_val32 x)
+{
+   int k;
+   opus_int32 x_frac;
+   if (x==0)
+      return 0;
+   else if (x>=1073741824)
+      return 2147483647; /* 2^31 -1 */
+   k = (celt_ilog2(x)>>1);
+   x_frac = VSHR32(x, 2*(k-14)-1);
+   x_frac = MULT32_32_Q31(celt_rsqrt_norm32(x_frac), x_frac);
+   if (k < 12) return PSHR32(x_frac, 12-k);
+   else return SHL32(x_frac, k-12);
+}
+
+#define L1 32767
+#define L2 -7651
+#define L3 8277
+#define L4 -626
+
+static OPUS_INLINE opus_val16 _celt_cos_pi_2(opus_val16 x)
+{
+   opus_val16 x2;
+
+   x2 = MULT16_16_P15(x,x);
+   return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2
+                                                                                ))))))));
+}
+
+#undef L1
+#undef L2
+#undef L3
+#undef L4
+
+opus_val16 celt_cos_norm(opus_val32 x)
+{
+   x = x&0x0001ffff;
+   if (x>SHL32(EXTEND32(1), 16))
+      x = SUB32(SHL32(EXTEND32(1), 17),x);
+   if (x&0x00007fff)
+   {
+      if (x<SHL32(EXTEND32(1), 15))
+      {
+         return _celt_cos_pi_2(EXTRACT16(x));
+      } else {
+         return NEG16(_celt_cos_pi_2(EXTRACT16(65536-x)));
+      }
+   } else {
+      if (x&0x0000ffff)
+         return 0;
+      else if (x&0x0001ffff)
+         return -32767;
+      else
+         return 32767;
+   }
+}
+
+/* Calculates the cosine of (PI*0.5*x) where the input x ranges from -1 to 1 and
+ * is in Q30 format. The output will also be in Q31 format. */
+opus_val32 celt_cos_norm32(opus_val32 x)
+{
+   static const opus_val32 COS_NORM_COEFF_A0 = 134217720;   /* Q27 */
+   static const opus_val32 COS_NORM_COEFF_A1 = -662336704;  /* Q29 */
+   static const opus_val32 COS_NORM_COEFF_A2 = 544710848;   /* Q31 */
+   static const opus_val32 COS_NORM_COEFF_A3 = -178761936;  /* Q33 */
+   static const opus_val32 COS_NORM_COEFF_A4 = 29487206;    /* Q35 */
+   opus_int32 x_sq_q29, tmp;
+   /* The expected x is in the range of [-1.0f, 1.0f] */
+   celt_sig_assert((x >= -1073741824) && (x <= 1073741824));
+   /* Make cos(+/- pi/2) exactly zero. */
+   if (ABS32(x) == 1<<30) return 0;
+   x_sq_q29 = MULT32_32_Q31(x, x);
+   /* Split evaluation in steps to avoid exploding macro expansion. */
+   tmp = ADD32(COS_NORM_COEFF_A3, MULT32_32_Q31(x_sq_q29, COS_NORM_COEFF_A4));
+   tmp = ADD32(COS_NORM_COEFF_A2, MULT32_32_Q31(x_sq_q29, tmp));
+   tmp = ADD32(COS_NORM_COEFF_A1, MULT32_32_Q31(x_sq_q29, tmp));
+   return SHL32(ADD32(COS_NORM_COEFF_A0, MULT32_32_Q31(x_sq_q29, tmp)), 4);
+}
+
+/* Computes a 16 bit approximate reciprocal (1/x) for a normalized Q15 input,
+ * resulting in a Q15 output. */
+opus_val16 celt_rcp_norm16(opus_val16 x)
+{
+   opus_val16 r;
+   /* Start with a linear approximation:
+      r = 1.8823529411764706-0.9411764705882353*n.
+      The coefficients and the result are Q14 in the range [15420,30840].*/
+   r = ADD16(30840, MULT16_16_Q15(-15420, x));
+   /* Perform two Newton iterations:
+      r -= r*((r*n)+(r-1.Q15))
+         = r*((r*n)+(r-1.Q15)). */
+   r = SUB16(r, MULT16_16_Q15(r,
+             ADD16(MULT16_16_Q15(r, x), ADD16(r, -32768))));
+   /* We subtract an extra 1 in the second iteration to avoid overflow; it also
+       neatly compensates for truncation error in the rest of the process. */
+   return SUB16(r, ADD16(1, MULT16_16_Q15(r,
+                ADD16(MULT16_16_Q15(r, x), ADD16(r, -32768)))));
+}
+
+/* Computes a 32 bit approximated reciprocal (1/x) for a normalized Q31 input,
+ * resulting in a Q30 output. The expected input range is [0.5f, 1.0f) in Q31
+ * and the expected output range is [1.0f, 2.0f) in Q30. */
+opus_val32 celt_rcp_norm32(opus_val32 x)
+{
+   opus_val32 r_q30;
+   celt_sig_assert(x >= 1073741824);
+   r_q30 = SHL32(EXTEND32(celt_rcp_norm16(SHR32(x, 15)-32768)), 16);
+   /* Solving f(y) = a - 1/y using the Newton Method
+    * Note: f(y)' = 1/y^2
+    * r = r - f(r)/f(r)' = r - (x * r*r - r)
+    *   = r - r*(r*x - 1)
+    * where
+    *   - r means 1/y's approximation.
+    *   - x means a, the input of function.
+    * Please note that:
+    *   - It adds 1 to avoid overflow
+    *   - -1.0f in Q30 is -1073741824. */
+   return SUB32(r_q30, ADD32(SHL32(
+                MULT32_32_Q31(ADD32(MULT32_32_Q31(r_q30, x), -1073741824),
+                              r_q30), 1), 1));
+}
+
+/** Reciprocal approximation (Q15 input, Q16 output) */
+opus_val32 celt_rcp(opus_val32 x)
+{
+   int i;
+   opus_val16 r;
+   celt_sig_assert(x>0);
+   i = celt_ilog2(x);
+
+   /* Compute the reciprocal of a Q15 number in the range [0, 1). */
+   r = celt_rcp_norm16(VSHR32(x,i-15)-32768);
+
+   /* r is now the Q15 solution to 2/(n+1), with a maximum relative error
+       of 7.05346E-5, a (relative) RMSE of 2.14418E-5, and a peak absolute
+       error of 1.24665/32768. */
+   return VSHR32(EXTEND32(r),i-16);
+}
+
+#endif
+
+#ifndef DISABLE_FLOAT_API
+
+void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt)
+{
+   int i;
+   for (i = 0; i < cnt; i++)
+   {
+      out[i] = FLOAT2INT16(in[i]);
+   }
+}
+
+int opus_limit2_checkwithin1_c(float * samples, int cnt)
+{
+   int i;
+   if (cnt <= 0)
+   {
+      return 1;
+   }
+
+   for (i = 0; i < cnt; i++)
+   {
+      float clippedVal = samples[i];
+      clippedVal = FMAX(-2.0f, clippedVal);
+      clippedVal = FMIN(2.0f, clippedVal);
+      samples[i] = clippedVal;
+   }
+
+   /* C implementation can't provide quick hint. Assume it might exceed -1/+1. */
+   return 0;
+}
+
+#endif /* DISABLE_FLOAT_API */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mathops.h
new file mode 100644 (file)
index 0000000..4b6fa15
--- /dev/null
@@ -0,0 +1,662 @@
+/* Copyright (c) 2002-2008 Jean-Marc Valin
+   Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2024 Arm Limited
+   Written by Jean-Marc Valin, and Yunho Huh */
+/**
+   @file mathops.h
+   @brief Various math functions
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MATHOPS_H
+#define MATHOPS_H
+
+#include "arch.h"
+#include "entcode.h"
+#include "os_support.h"
+
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+#include "arm/mathops_arm.h"
+#endif
+
+#define PI 3.1415926535897931
+
+/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
+#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
+
+unsigned isqrt32(opus_uint32 _val);
+
+/* CELT doesn't need it for fixed-point, by analysis.c does. */
+#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
+#define cA 0.43157974f
+#define cB 0.67848403f
+#define cC 0.08595542f
+#define cE ((float)PI/2)
+static OPUS_INLINE float fast_atan2f(float y, float x) {
+   float x2, y2;
+   x2 = x*x;
+   y2 = y*y;
+   /* For very small values, we don't care about the answer, so
+      we can just return 0. */
+   if (x2 + y2 < 1e-18f)
+   {
+      return 0;
+   }
+   if(x2<y2){
+      float den = (y2 + cB*x2) * (y2 + cC*x2);
+      return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
+   }else{
+      float den = (x2 + cB*y2) * (x2 + cC*y2);
+      return  x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+   }
+}
+#undef cA
+#undef cB
+#undef cC
+#undef cE
+#endif
+
+
+#ifndef OVERRIDE_CELT_MAXABS16
+static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
+{
+   int i;
+   opus_val16 maxval = 0;
+   opus_val16 minval = 0;
+   for (i=0;i<len;i++)
+   {
+      maxval = MAX16(maxval, x[i]);
+      minval = MIN16(minval, x[i]);
+   }
+   return MAX32(EXTEND32(maxval),-EXTEND32(minval));
+}
+#endif
+
+#if defined(ENABLE_RES24) && defined(FIXED_POINT)
+static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len)
+{
+   int i;
+   opus_res maxval = 0;
+   opus_res minval = 0;
+   for (i=0;i<len;i++)
+   {
+      maxval = MAX32(maxval, x[i]);
+      minval = MIN32(minval, x[i]);
+   }
+   /* opus_res should never reach such amplitude, so we should be safe. */
+   celt_sig_assert(minval != -2147483648);
+   return MAX32(maxval,-minval);
+}
+#else
+#define celt_maxabs_res celt_maxabs16
+#endif
+
+
+#ifndef OVERRIDE_CELT_MAXABS32
+#ifdef FIXED_POINT
+static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
+{
+   int i;
+   opus_val32 maxval = 0;
+   opus_val32 minval = 0;
+   for (i=0;i<len;i++)
+   {
+      maxval = MAX32(maxval, x[i]);
+      minval = MIN32(minval, x[i]);
+   }
+   return MAX32(maxval, -minval);
+}
+#else
+#define celt_maxabs32(x,len) celt_maxabs16(x,len)
+#endif
+#endif
+
+#ifndef FIXED_POINT
+/* Calculates the arctangent of x using a Remez approximation of order 15,
+ * incorporating only odd-powered terms. */
+static OPUS_INLINE float celt_atan_norm(float x)
+{
+   #define ATAN2_2_OVER_PI 0.636619772367581f
+   float x_sq = x * x;
+
+   /* Polynomial coefficients approximated in the [0, 1] range.
+    * Lolremez command: lolremez --degree 6 --range "0:1"
+    *                   "(atan(sqrt(x))-sqrt(x))/(x*sqrt(x))" "1/(sqrt(x)*x)"
+    * Please note that ATAN2_COEFF_A01 is fixed to 1.0f. */
+   #define ATAN2_COEFF_A03 -3.3331659436225891113281250000e-01f
+   #define ATAN2_COEFF_A05 1.99627041816711425781250000000e-01f
+   #define ATAN2_COEFF_A07 -1.3976582884788513183593750000e-01f
+   #define ATAN2_COEFF_A09 9.79423448443412780761718750000e-02f
+   #define ATAN2_COEFF_A11 -5.7773590087890625000000000000e-02f
+   #define ATAN2_COEFF_A13 2.30401363223791122436523437500e-02f
+   #define ATAN2_COEFF_A15 -4.3554059229791164398193359375e-03f
+   return ATAN2_2_OVER_PI * (x + x * x_sq * (ATAN2_COEFF_A03
+                + x_sq * (ATAN2_COEFF_A05
+                + x_sq * (ATAN2_COEFF_A07
+                + x_sq * (ATAN2_COEFF_A09
+                + x_sq * (ATAN2_COEFF_A11
+                + x_sq * (ATAN2_COEFF_A13
+                + x_sq * (ATAN2_COEFF_A15))))))));
+}
+
+/* Calculates the arctangent of y/x, returning an approximate value in radians.
+ * Please refer to the linked wiki page (https://en.wikipedia.org/wiki/Atan2)
+ * to learn how atan2 results are computed. */
+static OPUS_INLINE float celt_atan2p_norm(float y, float x)
+{
+   celt_sig_assert(x>=0 && y>=0);
+
+   /* For very small values, we don't care about the answer. */
+   if ((x*x + y*y) < 1e-18f)
+   {
+      return 0;
+   }
+
+   if (y < x)
+   {
+      return celt_atan_norm(y / x);
+   } else {
+      return 1.f - celt_atan_norm(x / y);
+   }
+}
+#endif
+
+#if !defined(FIXED_POINT) || defined(ENABLE_QEXT)
+/* Computes estimated cosine values for (PI/2 * x) using only terms with even
+ * exponents. */
+static OPUS_INLINE float celt_cos_norm2(float x)
+{
+   float x_norm_sq;
+   int output_sign;
+   /* Restrict x to [-1, 3]. */
+   x -= 4*floor(.25*(x+1));
+   /* Negative sign for [1, 3]. */
+   output_sign = 1 - 2*(x>1);
+   /* Restrict to [-1, 1]. */
+   x -= 2*(x>1);
+
+   /* The cosine function, cos(x), has a Taylor series representation consisting
+    * exclusively of even-powered polynomial terms. */
+   x_norm_sq = x * x;
+
+   /* Polynomial coefficients approximated in the [0, 1] range using only terms
+    * with even exponents.
+    * Lolremez command: lolremez --degree 4 --range 0:1 "cos(sqrt(x)*pi*0.5)" */
+   #define COS_COEFF_A0 9.999999403953552246093750000000e-01f
+   #define COS_COEFF_A2 -1.233698248863220214843750000000000f
+   #define COS_COEFF_A4 2.536507546901702880859375000000e-01f
+   #define COS_COEFF_A6 -2.08106283098459243774414062500e-02f
+   #define COS_COEFF_A8 8.581906440667808055877685546875e-04f
+   return output_sign * (COS_COEFF_A0 + x_norm_sq * (COS_COEFF_A2 +
+                               x_norm_sq * (COS_COEFF_A4 +
+                               x_norm_sq * (COS_COEFF_A6 +
+                               x_norm_sq * (COS_COEFF_A8)))));
+}
+
+#endif
+
+#ifndef FIXED_POINT
+
+#define celt_sqrt(x) ((float)sqrt(x))
+#define celt_sqrt32(x) ((float)sqrt(x))
+#define celt_rsqrt(x) (1.f/celt_sqrt(x))
+#define celt_rsqrt_norm(x) (celt_rsqrt(x))
+#define celt_rsqrt_norm32(x) (celt_rsqrt(x))
+#define celt_cos_norm(x) ((float)cos((.5f*PI)*(x)))
+#define celt_rcp(x) (1.f/(x))
+#define celt_div(a,b) ((a)/(b))
+#define frac_div32(a,b) ((float)(a)/(b))
+#define frac_div32_q29(a,b) frac_div32(a,b)
+
+#ifdef FLOAT_APPROX
+/* Calculates the base-2 logarithm (log2(x)) of a number. It is designed for
+ * systems using radix-2 floating-point representation, with the exponent
+ * located at bits 23 to 30 and an offset of 127. Note that special cases like
+ * denormalized numbers, positive/negative infinity, and NaN are not handled.
+ * log2(x) = log2(x^exponent * mantissa)
+ *         = exponent + log2(mantissa) */
+
+/* Log2 x normalization single precision coefficients calculated by
+ * 1 / (1 + 0.125 * index).
+ * Coefficients in Double Precision
+ * double log2_x_norm_coeff[8] = {
+ *    1.0000000000000000000, 8.888888888888888e-01,
+ *    8.000000000000000e-01, 7.272727272727273e-01,
+ *    6.666666666666666e-01, 6.153846153846154e-01,
+ *    5.714285714285714e-01, 5.333333333333333e-01} */
+static const float log2_x_norm_coeff[8] = {
+   1.000000000000000000000000000f, 8.88888895511627197265625e-01f,
+   8.00000000000000000000000e-01f, 7.27272748947143554687500e-01f,
+   6.66666686534881591796875e-01f, 6.15384638309478759765625e-01f,
+   5.71428596973419189453125e-01f, 5.33333361148834228515625e-01f};
+
+/* Log2 y normalization single precision coefficients calculated by
+ * log2(1 + 0.125 * index).
+ * Coefficients in Double Precision
+ * double log2_y_norm_coeff[8] = {
+ *    0.0000000000000000000, 1.699250014423124e-01,
+ *    3.219280948873623e-01, 4.594316186372973e-01,
+ *    5.849625007211562e-01, 7.004397181410922e-01,
+ *    8.073549220576041e-01, 9.068905956085185e-01}; */
+static const float log2_y_norm_coeff[8] = {
+   0.0000000000000000000000000000f, 1.699250042438507080078125e-01f,
+   3.219280838966369628906250e-01f, 4.594316184520721435546875e-01f,
+   5.849624872207641601562500e-01f, 7.004396915435791015625000e-01f,
+   8.073549270629882812500000e-01f, 9.068905711174011230468750e-01f};
+
+static OPUS_INLINE float celt_log2(float x)
+{
+   opus_int32 integer;
+   opus_int32 range_idx;
+   union {
+      float f;
+      opus_uint32 i;
+   } in;
+   in.f = x;
+   integer = (opus_int32)(in.i>>23)-127;
+   in.i = (opus_int32)in.i - (opus_int32)((opus_uint32)integer<<23);
+
+   /* Normalize the mantissa range from [1, 2] to [1,1.125], and then shift x
+    * by 1.0625 to [-0.0625, 0.0625]. */
+   range_idx = (in.i >> 20) & 0x7;
+   in.f = in.f * log2_x_norm_coeff[range_idx] - 1.0625f;
+
+   /* Polynomial coefficients approximated in the [1, 1.125] range.
+    * Lolremez command: lolremez --degree 4 --range -0.0625:0.0625
+    *                   "log(x+1.0625)/log(2)"
+    * Coefficients in Double Precision
+    * A0: 8.7462840624502679e-2    A1: 1.3578296070972002
+    * A2: -6.3897703690210047e-1   A3: 4.0197125617419959e-1
+    * A4: -2.8415445877832832e-1 */
+   #define LOG2_COEFF_A0 8.74628424644470214843750000e-02f
+   #define LOG2_COEFF_A1 1.357829570770263671875000000000f
+   #define LOG2_COEFF_A2 -6.3897705078125000000000000e-01f
+   #define LOG2_COEFF_A3 4.01971250772476196289062500e-01f
+   #define LOG2_COEFF_A4 -2.8415444493293762207031250e-01f
+   in.f = LOG2_COEFF_A0 + in.f * (LOG2_COEFF_A1
+               + in.f * (LOG2_COEFF_A2
+               + in.f * (LOG2_COEFF_A3
+               + in.f * (LOG2_COEFF_A4))));
+   return integer + in.f + log2_y_norm_coeff[range_idx];
+}
+
+/* Calculates an approximation of 2^x. The approximation was achieved by
+ * employing a base-2 exponential function and utilizing a Remez approximation
+ * of order 5, ensuring a controlled relative error.
+ * exp2(x) = exp2(integer + fraction)
+ *         = exp2(integer) * exp2(fraction) */
+static OPUS_INLINE float celt_exp2(float x)
+{
+   opus_int32 integer;
+   float frac;
+   union {
+      float f;
+      opus_uint32 i;
+   } res;
+   integer = (int)floor(x);
+   if (integer < -50)
+      return 0;
+   frac = x-integer;
+
+   /* Polynomial coefficients approximated in the [0, 1] range.
+    * Lolremez command: lolremez --degree 5 --range 0:1
+    *                   "exp(x*0.693147180559945)" "exp(x*0.693147180559945)"
+    * NOTE: log(2) ~ 0.693147180559945 */
+   #define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f
+   #define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f
+   #define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f
+   #define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f
+   #define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f
+   #define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f
+   res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1
+               + frac * (EXP2_COEFF_A2
+               + frac * (EXP2_COEFF_A3
+               + frac * (EXP2_COEFF_A4
+               + frac * (EXP2_COEFF_A5)))));
+   res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)integer<<23)) & 0x7fffffff;
+   return res.f;
+}
+
+#else
+#define celt_log2(x) ((float)(1.442695040888963387*log(x)))
+#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
+#endif
+
+#define celt_exp2_db celt_exp2
+#define celt_log2_db celt_log2
+
+#define celt_sin(x) celt_cos_norm2((0.5f*PI) * (x) - 1.0f)
+#define celt_log(x) (celt_log2(x) * 0.6931471805599453f)
+#define celt_exp(x) (celt_exp2((x) * 1.4426950408889634f))
+
+#endif
+
+#ifdef FIXED_POINT
+
+#include "os_support.h"
+
+#ifndef OVERRIDE_CELT_ILOG2
+/** Integer log in base2. Undefined for zero and negative numbers */
+static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
+{
+   celt_sig_assert(x>0);
+   return EC_ILOG(x)-1;
+}
+#endif
+
+
+/** Integer log in base2. Defined for zero, but not for negative numbers */
+static OPUS_INLINE opus_int16 celt_zlog2(opus_val32 x)
+{
+   return x <= 0 ? 0 : celt_ilog2(x);
+}
+
+opus_val16 celt_rsqrt_norm(opus_val32 x);
+
+opus_val32 celt_rsqrt_norm32(opus_val32 x);
+
+opus_val32 celt_sqrt(opus_val32 x);
+
+opus_val32 celt_sqrt32(opus_val32 x);
+
+opus_val16 celt_cos_norm(opus_val32 x);
+
+opus_val32 celt_cos_norm32(opus_val32 x);
+
+/** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */
+static OPUS_INLINE opus_val16 celt_log2(opus_val32 x)
+{
+   int i;
+   opus_val16 n, frac;
+   /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
+       0.15530808010959576, -0.08556153059057618 */
+   static const opus_val16 C[5] = {-6801+(1<<(13-10)), 15746, -5217, 2545, -1401};
+   if (x==0)
+      return -32767;
+   i = celt_ilog2(x);
+   n = VSHR32(x,i-15)-32768-16384;
+   frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
+   return SHL32(i-13,10)+SHR32(frac,14-10);
+}
+
+/*
+ K0 = 1
+ K1 = log(2)
+ K2 = 3-4*log(2)
+ K3 = 3*log(2) - 2
+*/
+#define D0 16383
+#define D1 22804
+#define D2 14819
+#define D3 10204
+
+static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x)
+{
+   opus_val16 frac;
+   frac = SHL16(x, 4);
+   return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
+}
+
+#undef D0
+#undef D1
+#undef D2
+#undef D3
+
+/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
+static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x)
+{
+   int integer;
+   opus_val16 frac;
+   integer = SHR16(x,10);
+   if (integer>14)
+      return 0x7f000000;
+   else if (integer < -15)
+      return 0;
+   frac = celt_exp2_frac(x-SHL16(integer,10));
+   return VSHR32(EXTEND32(frac), -integer-2);
+}
+
+#ifdef ENABLE_QEXT
+
+/* Calculates the base-2 logarithm of a Q14 input value. The result is returned
+ * in Q(DB_SHIFT). If the input value is 0, the function will output -32.0f. */
+static OPUS_INLINE opus_val32 celt_log2_db(opus_val32 x) {
+   /* Q30 */
+   static const opus_val32 log2_x_norm_coeff[8] = {
+      1073741824, 954437184, 858993472, 780903168,
+      715827904,  660764224, 613566784, 572662336};
+   /* Q24 */
+   static const opus_val32 log2_y_norm_coeff[8] = {
+      0,       2850868,  5401057,  7707983,
+      9814042, 11751428, 13545168, 15215099};
+   static const opus_val32 LOG2_COEFF_A0 = 1467383;     /* Q24 */
+   static const opus_val32 LOG2_COEFF_A1 = 182244800;   /* Q27 */
+   static const opus_val32 LOG2_COEFF_A2 = -21440512;   /* Q25 */
+   static const opus_val32 LOG2_COEFF_A3 = 107903336;   /* Q28 */
+   static const opus_val32 LOG2_COEFF_A4 = -610217024;  /* Q31 */
+
+   opus_int32 integer, norm_coeff_idx, tmp;
+   opus_val32 mantissa;
+   if (x==0) {
+      return -536870912; /* -32.0f */
+   }
+   integer =  SUB32(celt_ilog2(x), 14);  /* Q0 */
+   mantissa = VSHR32(x, integer + 14 - 29);  /* Q29 */
+   norm_coeff_idx = SHR32(mantissa, 29 - 3) & 0x7;
+   /* mantissa is in Q28 (29 + Q_NORM_CONST - 31 where Q_NORM_CONST is Q30)
+    * 285212672 (Q28) is 1.0625f. */
+   mantissa = SUB32(MULT32_32_Q31(mantissa, log2_x_norm_coeff[norm_coeff_idx]),
+                    285212672);
+
+   /* q_a3(Q28): q_mantissa + q_a4 - 31
+    * q_a2(Q25): q_mantissa + q_a3 - 31
+    * q_a1(Q27): q_mantissa + q_a2 - 31 + 5
+    * q_a0(Q24): q_mantissa + q_a1 - 31
+    * where  q_mantissa is Q28 */
+   /* Split evaluation in steps to avoid exploding macro expansion. */
+   tmp = MULT32_32_Q31(mantissa, LOG2_COEFF_A4);
+   tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A3, tmp));
+   tmp = SHL32(MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A2, tmp)), 5 /* SHL32 for LOG2_COEFF_A1 */);
+   tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A1, tmp));
+   return ADD32(log2_y_norm_coeff[norm_coeff_idx],
+          ADD32(SHL32(integer, DB_SHIFT),
+          ADD32(LOG2_COEFF_A0, tmp)));
+}
+
+/* Calculates exp2 for Q28 within a specific range (0 to 1.0) using fixed-point
+ * arithmetic. The input number must be adjusted for Q DB_SHIFT. */
+static OPUS_INLINE opus_val32 celt_exp2_db_frac(opus_val32 x)
+{
+   /* Approximation constants. */
+   static const opus_int32 EXP2_COEFF_A0 = 268435440;   /* Q28 */
+   static const opus_int32 EXP2_COEFF_A1 = 744267456;   /* Q30 */
+   static const opus_int32 EXP2_COEFF_A2 = 1031451904;  /* Q32 */
+   static const opus_int32 EXP2_COEFF_A3 = 959088832;   /* Q34 */
+   static const opus_int32 EXP2_COEFF_A4 = 617742720;   /* Q36 */
+   static const opus_int32 EXP2_COEFF_A5 = 516104352;   /* Q38 */
+   opus_int32 tmp;
+   /* Converts input value from Q24 to Q29. */
+   opus_val32 x_q29 = SHL32(x, 29 - 24);
+   /* Split evaluation in steps to avoid exploding macro expansion. */
+   tmp = ADD32(EXP2_COEFF_A4, MULT32_32_Q31(x_q29, EXP2_COEFF_A5));
+   tmp = ADD32(EXP2_COEFF_A3, MULT32_32_Q31(x_q29, tmp));
+   tmp = ADD32(EXP2_COEFF_A2, MULT32_32_Q31(x_q29, tmp));
+   tmp = ADD32(EXP2_COEFF_A1, MULT32_32_Q31(x_q29, tmp));
+   return ADD32(EXP2_COEFF_A0, MULT32_32_Q31(x_q29, tmp));
+}
+
+/* Calculates exp2 for Q16 using fixed-point arithmetic. The input number must
+ * be adjusted for Q DB_SHIFT. */
+static OPUS_INLINE opus_val32 celt_exp2_db(opus_val32 x)
+{
+   int integer;
+   opus_val32 frac;
+   integer = SHR32(x,DB_SHIFT);
+   if (integer>14)
+      return 0x7f000000;
+   else if (integer <= -17)
+      return 0;
+   frac = celt_exp2_db_frac(x-SHL32(integer, DB_SHIFT));  /* Q28 */
+   return VSHR32(frac, -integer + 28 - 16);  /* Q16 */
+}
+#else
+
+#define celt_log2_db(x) SHL32(EXTEND32(celt_log2(x)), DB_SHIFT-10)
+#define celt_exp2_db_frac(x) SHL32(celt_exp2_frac(PSHR32(x, DB_SHIFT-10)), 14)
+#define celt_exp2_db(x) celt_exp2(PSHR32(x, DB_SHIFT-10))
+
+#endif
+
+
+opus_val32 celt_rcp(opus_val32 x);
+opus_val32 celt_rcp_norm32(opus_val32 x);
+
+#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b))
+
+opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b);
+opus_val32 frac_div32(opus_val32 a, opus_val32 b);
+
+/* Computes atan(x) multiplied by 2/PI. The input value (x) should be within the
+ * range of -1 to 1 and represented in Q30 format. The function will return the
+ * result in Q30 format. */
+static OPUS_INLINE opus_val32 celt_atan_norm(opus_val32 x)
+{
+   /* Approximation constants. */
+   static const opus_int32 ATAN_2_OVER_PI = 1367130551;   /* Q31 */
+   static const opus_int32 ATAN_COEFF_A03 = -715791936;   /* Q31 */
+   static const opus_int32 ATAN_COEFF_A05 = 857391616;    /* Q32 */
+   static const opus_int32 ATAN_COEFF_A07 = -1200579328;  /* Q33 */
+   static const opus_int32 ATAN_COEFF_A09 = 1682636672;   /* Q34 */
+   static const opus_int32 ATAN_COEFF_A11 = -1985085440;  /* Q35 */
+   static const opus_int32 ATAN_COEFF_A13 = 1583306112;   /* Q36 */
+   static const opus_int32 ATAN_COEFF_A15 = -598602432;   /* Q37 */
+   opus_int32 x_sq_q30;
+   opus_int32 x_q31;
+   opus_int32 tmp;
+   /* The expected x is in the range of [-1.0f, 1.0f] */
+   celt_sig_assert((x <= 1073741824) && (x >= -1073741824));
+
+   /* If x = 1.0f, returns 0.5f */
+   if (x == 1073741824)
+   {
+      return 536870912; /* 0.5f (Q30) */
+   }
+   /* If x = 1.0f, returns 0.5f */
+   if (x == -1073741824)
+   {
+      return -536870912; /* -0.5f (Q30) */
+   }
+   x_q31 = SHL32(x, 1);
+   x_sq_q30 = MULT32_32_Q31(x_q31, x);
+   /* Split evaluation in steps to avoid exploding macro expansion. */
+   tmp = MULT32_32_Q31(x_sq_q30, ATAN_COEFF_A15);
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A13, tmp));
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A11, tmp));
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A09, tmp));
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A07, tmp));
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A05, tmp));
+   tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A03, tmp));
+   tmp = ADD32(x, MULT32_32_Q31(x_q31, tmp));
+   return MULT32_32_Q31(ATAN_2_OVER_PI, tmp);
+}
+
+/* Calculates the arctangent of y/x, multiplies the result by 2/pi, and returns
+ * the value in Q30 format. Both input values (x and y) must be within the range
+ * of 0 to 1 and represented in Q30 format. Inputs must be zero or greater, and
+ * at least one input must be non-zero. */
+static OPUS_INLINE opus_val32 celt_atan2p_norm(opus_val32 y, opus_val32 x)
+{
+   celt_sig_assert(x>=0 && y>=0);
+   if (y==0 && x==0) {
+      return 0;
+   } else if (y < x) {
+      return celt_atan_norm(SHR32(frac_div32(y, x), 1));
+   } else {
+      celt_sig_assert(y > 0);
+      return 1073741824 /* 1.0f Q30 */ -
+             celt_atan_norm(SHR32(frac_div32(x, y), 1));
+   }
+}
+
+#define M1 32767
+#define M2 -21
+#define M3 -11943
+#define M4 4936
+
+/* Atan approximation using a 4th order polynomial. Input is in Q15 format
+   and normalized by pi/4. Output is in Q15 format */
+static OPUS_INLINE opus_val16 celt_atan01(opus_val16 x)
+{
+   return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
+}
+
+#undef M1
+#undef M2
+#undef M3
+#undef M4
+
+/* atan2() approximation valid for positive input values */
+static OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x)
+{
+   if (x==0 && y==0) {
+      return 0;
+   } else if (y < x)
+   {
+      opus_val32 arg;
+      arg = celt_div(SHL32(EXTEND32(y),15),x);
+      if (arg >= 32767)
+         arg = 32767;
+      return SHR16(celt_atan01(EXTRACT16(arg)),1);
+   } else {
+      opus_val32 arg;
+      arg = celt_div(SHL32(EXTEND32(x),15),y);
+      if (arg >= 32767)
+         arg = 32767;
+      return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1);
+   }
+}
+
+#endif /* FIXED_POINT */
+
+#ifndef DISABLE_FLOAT_API
+
+void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt);
+
+#ifndef OVERRIDE_FLOAT2INT16
+#define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_c(in, out, cnt))
+#endif
+
+int opus_limit2_checkwithin1_c(float *samples, int cnt);
+
+#ifndef OVERRIDE_LIMIT2_CHECKWITHIN1
+#define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_c(samples, cnt))
+#endif
+
+#endif /* DISABLE_FLOAT_API */
+
+#endif /* MATHOPS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.c
new file mode 100644 (file)
index 0000000..2b8a0bc
--- /dev/null
@@ -0,0 +1,390 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2008 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* This is a simple MDCT implementation that uses a N/4 complex FFT
+   to do most of the work. It should be relatively straightforward to
+   plug in pretty much and FFT here.
+
+   This replaces the Vorbis FFT (and uses the exact same API), which
+   was a bit too messy and that was ending up duplicating code
+   (might as well use the same FFT everywhere).
+
+   The algorithm is similar to (and inspired from) Fabrice Bellard's
+   MDCT implementation in FFMPEG, but has differences in signs, ordering
+   and scaling in many places.
+*/
+
+#ifndef SKIP_CONFIG_H
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#endif
+
+#include "mdct.h"
+#include "kiss_fft.h"
+#include "_kiss_fft_guts.h"
+#include <math.h>
+#include "os_support.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+
+#if defined(FIXED_POINT) && defined(__mips) && __mips == 32
+#include "mips/mdct_mipsr1.h"
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+#ifdef CUSTOM_MODES
+
+int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch)
+{
+   int i;
+   kiss_twiddle_scalar *trig;
+   int shift;
+   int N2=N>>1;
+   l->n = N;
+   l->maxshift = maxshift;
+   for (i=0;i<=maxshift;i++)
+   {
+      if (i==0)
+         l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0, arch);
+      else
+         l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0], arch);
+#ifndef ENABLE_TI_DSPLIB55
+      if (l->kfft[i]==NULL)
+         return 0;
+#endif
+   }
+   l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N-(N2>>maxshift))*sizeof(kiss_twiddle_scalar));
+   if (l->trig==NULL)
+     return 0;
+   for (shift=0;shift<=maxshift;shift++)
+   {
+      /* We have enough points that sine isn't necessary */
+#if defined(FIXED_POINT)
+#ifndef ENABLE_QEXT
+      for (i=0;i<N2;i++)
+         trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N));
+#else
+      for (i=0;i<N2;i++)
+         trig[i] = (kiss_twiddle_scalar)MAX32(-2147483647,MIN32(2147483647,floor(.5+2147483648*cos(2*M_PI*(i+.125)/N))));
+#endif
+#else
+      for (i=0;i<N2;i++)
+         trig[i] = (kiss_twiddle_scalar)cos(2*PI*(i+.125)/N);
+#endif
+      trig += N2;
+      N2 >>= 1;
+      N >>= 1;
+   }
+   return 1;
+}
+
+void clt_mdct_clear(mdct_lookup *l, int arch)
+{
+   int i;
+   for (i=0;i<=l->maxshift;i++)
+      opus_fft_free(l->kfft[i], arch);
+   opus_free((kiss_twiddle_scalar*)l->trig);
+}
+
+#endif /* CUSTOM_MODES */
+
+/* Forward MDCT trashes the input array */
+#ifndef OVERRIDE_clt_mdct_forward
+void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
+      const celt_coef *window, int overlap, int shift, int stride, int arch)
+{
+   int i;
+   int N, N2, N4;
+   VARDECL(kiss_fft_scalar, f);
+   VARDECL(kiss_fft_cpx, f2);
+   const kiss_fft_state *st = l->kfft[shift];
+   const kiss_twiddle_scalar *trig;
+   celt_coef scale;
+#ifdef FIXED_POINT
+   /* Allows us to scale with MULT16_32_Q16(), which is faster than
+      MULT16_32_Q15() on ARM. */
+   int scale_shift = st->scale_shift-1;
+   int headroom;
+#endif
+   SAVE_STACK;
+   (void)arch;
+   scale = st->scale;
+
+   N = l->n;
+   trig = l->trig;
+   for (i=0;i<shift;i++)
+   {
+      N >>= 1;
+      trig += N;
+   }
+   N2 = N>>1;
+   N4 = N>>2;
+
+   ALLOC(f, N2, kiss_fft_scalar);
+   ALLOC(f2, N4, kiss_fft_cpx);
+
+   /* Consider the input to be composed of four blocks: [a, b, c, d] */
+   /* Window, shuffle, fold */
+   {
+      /* Temp pointers to make it really clear to the compiler what we're doing */
+      const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
+      const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
+      kiss_fft_scalar * OPUS_RESTRICT yp = f;
+      const celt_coef * OPUS_RESTRICT wp1 = window+(overlap>>1);
+      const celt_coef * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
+      for(i=0;i<((overlap+3)>>2);i++)
+      {
+         /* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
+         *yp++ = S_MUL(xp1[N2], *wp2) + S_MUL(*xp2, *wp1);
+         *yp++ = S_MUL(*xp1, *wp1)    - S_MUL(xp2[-N2], *wp2);
+         xp1+=2;
+         xp2-=2;
+         wp1+=2;
+         wp2-=2;
+      }
+      wp1 = window;
+      wp2 = window+overlap-1;
+      for(;i<N4-((overlap+3)>>2);i++)
+      {
+         /* Real part arranged as a-bR, Imag part arranged as -c-dR */
+         *yp++ = *xp2;
+         *yp++ = *xp1;
+         xp1+=2;
+         xp2-=2;
+      }
+      for(;i<N4;i++)
+      {
+         /* Real part arranged as a-bR, Imag part arranged as -c-dR */
+         *yp++ =  -S_MUL(xp1[-N2], *wp1) + S_MUL(*xp2, *wp2);
+         *yp++ = S_MUL(*xp1, *wp2)     + S_MUL(xp2[N2], *wp1);
+         xp1+=2;
+         xp2-=2;
+         wp1+=2;
+         wp2-=2;
+      }
+   }
+   /* Pre-rotation */
+   {
+      kiss_fft_scalar * OPUS_RESTRICT yp = f;
+      const kiss_twiddle_scalar *t = &trig[0];
+#ifdef FIXED_POINT
+      opus_val32 maxval=1;
+#endif
+      for(i=0;i<N4;i++)
+      {
+         kiss_fft_cpx yc;
+         kiss_twiddle_scalar t0, t1;
+         kiss_fft_scalar re, im, yr, yi;
+         t0 = t[i];
+         t1 = t[N4+i];
+         re = *yp++;
+         im = *yp++;
+         yr = S_MUL(re,t0)  -  S_MUL(im,t1);
+         yi = S_MUL(im,t0)  +  S_MUL(re,t1);
+         /* For QEXT, it's best to scale before the FFT, but otherwise it's best to scale after.
+            For floating-point it doesn't matter. */
+#ifdef ENABLE_QEXT
+         yc.r = yr;
+         yc.i = yi;
+#else
+         yc.r = S_MUL2(yr, scale);
+         yc.i = S_MUL2(yi, scale);
+#endif
+#ifdef FIXED_POINT
+         maxval = MAX32(maxval, MAX32(ABS32(yc.r), ABS32(yc.i)));
+#endif
+         f2[st->bitrev[i]] = yc;
+      }
+#ifdef FIXED_POINT
+      headroom = IMAX(0, IMIN(scale_shift, 28-celt_ilog2(maxval)));
+#endif
+   }
+
+   /* N/4 complex FFT, does not downscale anymore */
+   opus_fft_impl(st, f2 ARG_FIXED(scale_shift-headroom));
+
+   /* Post-rotate */
+   {
+      /* Temp pointers to make it really clear to the compiler what we're doing */
+      const kiss_fft_cpx * OPUS_RESTRICT fp = f2;
+      kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
+      kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
+      const kiss_twiddle_scalar *t = &trig[0];
+      /* Temp pointers to make it really clear to the compiler what we're doing */
+      for(i=0;i<N4;i++)
+      {
+         kiss_fft_scalar yr, yi;
+         kiss_fft_scalar t0, t1;
+#ifdef ENABLE_QEXT
+         t0 = S_MUL2(t[i], scale);
+         t1 = S_MUL2(t[N4+i], scale);
+#else
+         t0 = t[i];
+         t1 = t[N4+i];
+#endif
+         yr = PSHR32(S_MUL(fp->i,t1) - S_MUL(fp->r,t0), headroom);
+         yi = PSHR32(S_MUL(fp->r,t1) + S_MUL(fp->i,t0), headroom);
+         *yp1 = yr;
+         *yp2 = yi;
+         fp++;
+         yp1 += 2*stride;
+         yp2 -= 2*stride;
+      }
+   }
+   RESTORE_STACK;
+}
+#endif /* OVERRIDE_clt_mdct_forward */
+
+#ifndef OVERRIDE_clt_mdct_backward
+void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
+      const celt_coef * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
+{
+   int i;
+   int N, N2, N4;
+   const kiss_twiddle_scalar *trig;
+#ifdef FIXED_POINT
+   int pre_shift, post_shift, fft_shift;
+#endif
+   (void) arch;
+
+   N = l->n;
+   trig = l->trig;
+   for (i=0;i<shift;i++)
+   {
+      N >>= 1;
+      trig += N;
+   }
+   N2 = N>>1;
+   N4 = N>>2;
+
+#ifdef FIXED_POINT
+   {
+      opus_val32 sumval=N2;
+      opus_val32 maxval=0;
+      for (i=0;i<N2;i++) {
+         maxval = MAX32(maxval, ABS32(in[i*stride]));
+         sumval = ADD32_ovflw(sumval, ABS32(SHR32(in[i*stride],11)));
+      }
+      pre_shift = IMAX(0, 29-celt_zlog2(1+maxval));
+      /* Worst-case where all the energy goes to a single sample. */
+      post_shift = IMAX(0, 19-celt_ilog2(ABS32(sumval)));
+      post_shift = IMIN(post_shift, pre_shift);
+      fft_shift = pre_shift - post_shift;
+   }
+#endif
+   /* Pre-rotate */
+   {
+      /* Temp pointers to make it really clear to the compiler what we're doing */
+      const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
+      const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
+      kiss_fft_scalar * OPUS_RESTRICT yp = out+(overlap>>1);
+      const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
+      const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev;
+      for(i=0;i<N4;i++)
+      {
+         int rev;
+         kiss_fft_scalar yr, yi;
+         opus_val32 x1, x2;
+         rev = *bitrev++;
+         x1 = SHL32_ovflw(*xp1, pre_shift);
+         x2 = SHL32_ovflw(*xp2, pre_shift);
+         yr = ADD32_ovflw(S_MUL(x2, t[i]), S_MUL(x1, t[N4+i]));
+         yi = SUB32_ovflw(S_MUL(x1, t[i]), S_MUL(x2, t[N4+i]));
+         /* We swap real and imag because we use an FFT instead of an IFFT. */
+         yp[2*rev+1] = yr;
+         yp[2*rev] = yi;
+         /* Storing the pre-rotation directly in the bitrev order. */
+         xp1+=2*stride;
+         xp2-=2*stride;
+      }
+   }
+
+   opus_fft_impl(l->kfft[shift], (kiss_fft_cpx*)(out+(overlap>>1)) ARG_FIXED(fft_shift));
+
+   /* Post-rotate and de-shuffle from both ends of the buffer at once to make
+      it in-place. */
+   {
+      kiss_fft_scalar * yp0 = out+(overlap>>1);
+      kiss_fft_scalar * yp1 = out+(overlap>>1)+N2-2;
+      const kiss_twiddle_scalar *t = &trig[0];
+      /* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the
+         middle pair will be computed twice. */
+      for(i=0;i<(N4+1)>>1;i++)
+      {
+         kiss_fft_scalar re, im, yr, yi;
+         kiss_twiddle_scalar t0, t1;
+         /* We swap real and imag because we're using an FFT instead of an IFFT. */
+         re = yp0[1];
+         im = yp0[0];
+         t0 = t[i];
+         t1 = t[N4+i];
+         /* We'd scale up by 2 here, but instead it's done when mixing the windows */
+         yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift);
+         yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift);
+         /* We swap real and imag because we're using an FFT instead of an IFFT. */
+         re = yp1[1];
+         im = yp1[0];
+         yp0[0] = yr;
+         yp1[1] = yi;
+
+         t0 = t[(N4-i-1)];
+         t1 = t[(N2-i-1)];
+         /* We'd scale up by 2 here, but instead it's done when mixing the windows */
+         yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift);
+         yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift);
+         yp1[0] = yr;
+         yp0[1] = yi;
+         yp0 += 2;
+         yp1 -= 2;
+      }
+   }
+
+   /* Mirror on both sides for TDAC */
+   {
+      kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1;
+      kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
+      const celt_coef * OPUS_RESTRICT wp1 = window;
+      const celt_coef * OPUS_RESTRICT wp2 = window+overlap-1;
+
+      for(i = 0; i < overlap/2; i++)
+      {
+         kiss_fft_scalar x1, x2;
+         x1 = *xp1;
+         x2 = *yp1;
+         *yp1++ = SUB32_ovflw(S_MUL(x2, *wp2), S_MUL(x1, *wp1));
+         *xp1-- = ADD32_ovflw(S_MUL(x2, *wp1), S_MUL(x1, *wp2));
+         wp1++;
+         wp2--;
+      }
+   }
+}
+#endif /* OVERRIDE_clt_mdct_backward */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mdct.h
new file mode 100644 (file)
index 0000000..529b706
--- /dev/null
@@ -0,0 +1,111 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2008 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* This is a simple MDCT implementation that uses a N/4 complex FFT
+   to do most of the work. It should be relatively straightforward to
+   plug in pretty much and FFT here.
+
+   This replaces the Vorbis FFT (and uses the exact same API), which
+   was a bit too messy and that was ending up duplicating code
+   (might as well use the same FFT everywhere).
+
+   The algorithm is similar to (and inspired from) Fabrice Bellard's
+   MDCT implementation in FFMPEG, but has differences in signs, ordering
+   and scaling in many places.
+*/
+
+#ifndef MDCT_H
+#define MDCT_H
+
+#include "opus_defines.h"
+#include "kiss_fft.h"
+#include "arch.h"
+
+typedef struct {
+   int n;
+   int maxshift;
+   const kiss_fft_state *kfft[4];
+   const kiss_twiddle_scalar * OPUS_RESTRICT trig;
+} mdct_lookup;
+
+#if defined(HAVE_ARM_NE10)
+#include "arm/mdct_arm.h"
+#endif
+
+int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch);
+void clt_mdct_clear(mdct_lookup *l, int arch);
+
+/** Compute a forward MDCT and scale by 4/N, trashes the input array */
+void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in,
+                        kiss_fft_scalar * OPUS_RESTRICT out,
+                        const celt_coef *window, int overlap,
+                        int shift, int stride, int arch);
+
+/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
+    (scales implicitly by 1/2) */
+void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
+      kiss_fft_scalar * OPUS_RESTRICT out,
+      const celt_coef * OPUS_RESTRICT window,
+      int overlap, int shift, int stride, int arch);
+
+#if !defined(OVERRIDE_OPUS_MDCT)
+/* Is run-time CPU detection enabled on this platform? */
+#if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10)
+
+extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(
+      const mdct_lookup *l, kiss_fft_scalar *in,
+      kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
+      int overlap, int shift, int stride, int arch);
+
+#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+   ((*CLT_MDCT_FORWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
+                                                   _window, _overlap, _shift, \
+                                                   _stride, _arch))
+
+extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(
+      const mdct_lookup *l, kiss_fft_scalar *in,
+      kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
+      int overlap, int shift, int stride, int arch);
+
+#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+   (*CLT_MDCT_BACKWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
+                                                   _window, _overlap, _shift, \
+                                                   _stride, _arch)
+
+#else /* if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) */
+
+#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+   clt_mdct_forward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
+
+#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+   clt_mdct_backward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
+
+#endif /* end if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) && !defined(FIXED_POINT) */
+#endif /* end if !defined(OVERRIDE_OPUS_MDCT) */
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mfrngcod.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/mfrngcod.h
new file mode 100644 (file)
index 0000000..809152a
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright (c) 2001-2008 Timothy B. Terriberry
+   Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if !defined(_mfrngcode_H)
+# define _mfrngcode_H (1)
+# include "entcode.h"
+
+/*Constants used by the entropy encoder/decoder.*/
+
+/*The number of bits to output at a time.*/
+# define EC_SYM_BITS   (8)
+/*The total number of bits in each of the state registers.*/
+# define EC_CODE_BITS  (32)
+/*The maximum symbol value.*/
+# define EC_SYM_MAX    ((1U<<EC_SYM_BITS)-1)
+/*Bits to shift by to move a symbol into the high-order position.*/
+# define EC_CODE_SHIFT (EC_CODE_BITS-EC_SYM_BITS-1)
+/*Carry bit of the high-order range symbol.*/
+# define EC_CODE_TOP   (((opus_uint32)1U)<<(EC_CODE_BITS-1))
+/*Low-order bit of the high-order range symbol.*/
+# define EC_CODE_BOT   (EC_CODE_TOP>>EC_SYM_BITS)
+/*The number of bits available for the last, partial symbol in the code field.*/
+# define EC_CODE_EXTRA ((EC_CODE_BITS-2)%EC_SYM_BITS+1)
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.c
new file mode 100644 (file)
index 0000000..1f4abcf
--- /dev/null
@@ -0,0 +1,520 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "celt.h"
+#include "modes.h"
+#include "rate.h"
+#include "os_support.h"
+#include "stack_alloc.h"
+#include "quant_bands.h"
+#include "cpu_support.h"
+
+static const opus_int16 eband5ms[] = {
+/*0  200 400 600 800  1k 1.2 1.4 1.6  2k 2.4 2.8 3.2  4k 4.8 5.6 6.8  8k 9.6 12k 15.6 */
+  0,  1,  2,  3,  4,  5,  6,  7,  8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
+};
+
+/* Alternate tuning (partially derived from Vorbis) */
+#define BITALLOC_SIZE 11
+/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
+static const unsigned char band_allocation[] = {
+/*0  200 400 600 800  1k 1.2 1.4 1.6  2k 2.4 2.8 3.2  4k 4.8 5.6 6.8  8k 9.6 12k 15.6 */
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+ 90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10,  0,  0,  0,  0,  0,  0,  0,  0,
+110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12,  0,  0,  0,  0,  0,  0,
+118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15,  4,  0,  0,  0,  0,
+126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12,  1,  0,  0,
+134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10,  1,
+144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15,  1,
+152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20,  1,
+162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30,  1,
+172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
+200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,
+};
+
+#ifndef CUSTOM_MODES_ONLY
+ #ifdef FIXED_POINT
+  #include "static_modes_fixed.h"
+ #else
+  #include "static_modes_float.h"
+ #endif
+#endif /* CUSTOM_MODES_ONLY */
+
+#ifndef M_PI
+#define M_PI 3.1415926535897931
+#endif
+
+#ifdef CUSTOM_MODES
+
+/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
+   Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
+#define BARK_BANDS 25
+static const opus_int16 bark_freq[BARK_BANDS+1] = {
+      0,   100,   200,   300,   400,
+    510,   630,   770,   920,  1080,
+   1270,  1480,  1720,  2000,  2320,
+   2700,  3150,  3700,  4400,  5300,
+   6400,  7700,  9500, 12000, 15500,
+  20000};
+
+static opus_int16 *compute_ebands(opus_int32 Fs, int frame_size, int res, int *nbEBands)
+{
+   opus_int16 *eBands;
+   int i, j, lin, low, high, nBark, offset=0;
+
+   /* All modes that have 2.5 ms short blocks use the same definition */
+   if (Fs == 400*(opus_int32)frame_size)
+   {
+      *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
+      eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+1));
+      for (i=0;i<*nbEBands+1;i++)
+         eBands[i] = eband5ms[i];
+      return eBands;
+   }
+   /* Find the number of critical bands supported by our sampling rate */
+   for (nBark=1;nBark<BARK_BANDS;nBark++)
+    if (bark_freq[nBark+1]*2 >= Fs)
+       break;
+
+   /* Find where the linear part ends (i.e. where the spacing is more than min_width */
+   for (lin=0;lin<nBark;lin++)
+      if (bark_freq[lin+1]-bark_freq[lin] >= res)
+         break;
+
+   low = (bark_freq[lin]+res/2)/res;
+   high = nBark-lin;
+   *nbEBands = low+high;
+   eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+2));
+
+   if (eBands==NULL)
+      return NULL;
+
+   /* Linear spacing (min_width) */
+   for (i=0;i<low;i++)
+      eBands[i] = i;
+   if (low>0)
+      offset = eBands[low-1]*res - bark_freq[lin-1];
+   /* Spacing follows critical bands */
+   for (i=0;i<high;i++)
+   {
+      int target = bark_freq[lin+i];
+      /* Round to an even value */
+      eBands[i+low] = (target+offset/2+res)/(2*res)*2;
+      offset = eBands[i+low]*res - target;
+   }
+   /* Enforce the minimum spacing at the boundary */
+   for (i=0;i<*nbEBands;i++)
+      if (eBands[i] < i)
+         eBands[i] = i;
+   /* Round to an even value */
+   eBands[*nbEBands] = (bark_freq[nBark]+res)/(2*res)*2;
+   if (eBands[*nbEBands] > frame_size)
+      eBands[*nbEBands] = frame_size;
+   for (i=1;i<*nbEBands-1;i++)
+   {
+      if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
+      {
+         eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
+      }
+   }
+   /* Remove any empty bands. */
+   for (i=j=0;i<*nbEBands;i++)
+      if(eBands[i+1]>eBands[j])
+         eBands[++j]=eBands[i+1];
+   *nbEBands=j;
+
+   for (i=1;i<*nbEBands;i++)
+   {
+      /* Every band must be smaller than the last band. */
+      celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]);
+      /* Each band must be no larger than twice the size of the previous one. */
+      celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1]));
+   }
+
+   return eBands;
+}
+
+static void compute_allocation_table(CELTMode *mode)
+{
+   int i, j;
+   unsigned char *allocVectors;
+   int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
+
+   mode->nbAllocVectors = BITALLOC_SIZE;
+   allocVectors = opus_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
+   if (allocVectors==NULL)
+   {
+      mode->allocVectors = NULL;
+      return;
+   }
+
+   /* Check for standard mode */
+   if (mode->Fs == 400*(opus_int32)mode->shortMdctSize)
+   {
+      for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
+         allocVectors[i] = band_allocation[i];
+      mode->allocVectors = allocVectors;
+      return;
+   }
+   /* If not the standard mode, interpolate */
+   /* Compute per-codec-band allocation from per-critical-band matrix */
+   for (i=0;i<BITALLOC_SIZE;i++)
+   {
+      for (j=0;j<mode->nbEBands;j++)
+      {
+         int k;
+         for (k=0;k<maxBands;k++)
+         {
+            if (400*(opus_int32)eband5ms[k] > mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize)
+               break;
+         }
+         if (k>maxBands-1)
+            allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
+         else {
+            opus_int32 a0, a1;
+            a1 = mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize - 400*(opus_int32)eband5ms[k-1];
+            a0 = 400*(opus_int32)eband5ms[k] - mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize;
+            allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
+                                             + a1*band_allocation[i*maxBands+k])/(a0+a1);
+         }
+      }
+   }
+
+   /*printf ("\n");
+   for (i=0;i<BITALLOC_SIZE;i++)
+   {
+      for (j=0;j<mode->nbEBands;j++)
+         printf ("%d ", allocVectors[i*mode->nbEBands+j]);
+      printf ("\n");
+   }
+   exit(0);*/
+
+   mode->allocVectors = allocVectors;
+}
+
+#endif /* CUSTOM_MODES */
+
+CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
+{
+   int i;
+#ifdef CUSTOM_MODES
+   CELTMode *mode=NULL;
+   int res;
+   celt_coef *window;
+   opus_int16 *logN;
+   int LM;
+   int arch = opus_select_arch();
+   ALLOC_STACK;
+#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
+   if (global_stack==NULL)
+      goto failure;
+#endif
+#endif
+
+#ifndef CUSTOM_MODES_ONLY
+   for (i=0;i<TOTAL_MODES;i++)
+   {
+      int j;
+      for (j=0;j<4;j++)
+      {
+         if (Fs == static_mode_list[i]->Fs &&
+               (frame_size<<j) == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
+         {
+            if (error)
+               *error = OPUS_OK;
+            return (CELTMode*)static_mode_list[i];
+         }
+      }
+   }
+#endif /* CUSTOM_MODES_ONLY */
+
+#ifndef CUSTOM_MODES
+   if (error)
+      *error = OPUS_BAD_ARG;
+   return NULL;
+#else
+
+   /* The good thing here is that permutation of the arguments will automatically be invalid */
+
+   if (Fs < 8000 || Fs > 96000)
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+#ifdef ENABLE_QEXT
+   if (frame_size < 40 || frame_size > 2048 || frame_size%2!=0)
+#else
+   if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
+#endif
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+   /* Frames of less than 1ms are not supported. */
+   if ((opus_int32)frame_size*1000 < Fs)
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+
+   if ((opus_int32)frame_size*75 >= Fs && (frame_size%16)==0)
+   {
+     LM = 3;
+   } else if ((opus_int32)frame_size*150 >= Fs && (frame_size%8)==0)
+   {
+     LM = 2;
+   } else if ((opus_int32)frame_size*300 >= Fs && (frame_size%4)==0)
+   {
+     LM = 1;
+   } else
+   {
+     LM = 0;
+   }
+
+   /* Shorts longer than 3.3ms are not supported. */
+   if ((opus_int32)(frame_size>>LM)*300 > Fs)
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+
+   mode = opus_alloc(sizeof(CELTMode));
+   if (mode==NULL)
+      goto failure;
+   mode->Fs = Fs;
+
+   /* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
+      is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
+      approximate that. */
+#ifdef ENABLE_QEXT
+   if(Fs == 96000) /* 96 kHz */
+   {
+      mode->preemph[0] =  QCONST16(0.9230041504f, 15);
+      mode->preemph[1] =  QCONST16(0.2200012207f, 15);
+      mode->preemph[2] =  QCONST16(1.5128347184f, SIG_SHIFT); /* exact 1/preemph[3] */
+      mode->preemph[3] =  QCONST16(0.6610107422f, 13);
+   } else
+#endif
+   if(Fs < 12000) /* 8 kHz */
+   {
+      mode->preemph[0] =  QCONST16(0.3500061035f, 15);
+      mode->preemph[1] = -QCONST16(0.1799926758f, 15);
+      mode->preemph[2] =  QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */
+      mode->preemph[3] =  QCONST16(3.6765136719f, 13);
+   } else if(Fs < 24000) /* 16 kHz */
+   {
+      mode->preemph[0] =  QCONST16(0.6000061035f, 15);
+      mode->preemph[1] = -QCONST16(0.1799926758f, 15);
+      mode->preemph[2] =  QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */
+      mode->preemph[3] =  QCONST16(2.2598876953f, 13);
+   } else if(Fs < 40000) /* 32 kHz */
+   {
+      mode->preemph[0] =  QCONST16(0.7799987793f, 15);
+      mode->preemph[1] = -QCONST16(0.1000061035f, 15);
+      mode->preemph[2] =  QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */
+      mode->preemph[3] =  QCONST16(1.3333740234f, 13);
+   } else /* 48 kHz */
+   {
+      mode->preemph[0] =  QCONST16(0.8500061035f, 15);
+      mode->preemph[1] =  QCONST16(0.0f, 15);
+      mode->preemph[2] =  QCONST16(1.f, SIG_SHIFT);
+      mode->preemph[3] =  QCONST16(1.f, 13);
+   }
+
+   mode->maxLM = LM;
+   mode->nbShortMdcts = 1<<LM;
+   mode->shortMdctSize = frame_size/mode->nbShortMdcts;
+   res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
+
+   mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
+   if (mode->eBands==NULL)
+      goto failure;
+#if !defined(SMALL_FOOTPRINT)
+   /* Make sure we don't allocate a band larger than our PVQ table.
+      208 should be enough, but let's be paranoid. */
+   if ((mode->eBands[mode->nbEBands] - mode->eBands[mode->nbEBands-1])<<LM >
+    208) {
+       goto failure;
+   }
+#endif
+
+   mode->effEBands = mode->nbEBands;
+   while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
+      mode->effEBands--;
+
+   /* Overlap must be divisible by 4 */
+   mode->overlap = ((mode->shortMdctSize>>2)<<2);
+
+   compute_allocation_table(mode);
+   if (mode->allocVectors==NULL)
+      goto failure;
+
+   window = (celt_coef*)opus_alloc(mode->overlap*sizeof(*window));
+   if (window==NULL)
+      goto failure;
+
+#ifndef FIXED_POINT
+   for (i=0;i<mode->overlap;i++)
+      window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
+#else
+# ifdef ENABLE_QEXT
+   for (i=0;i<mode->overlap;i++)
+      window[i] = MIN32(2147483647, 2147483648*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)));
+# else
+   for (i=0;i<mode->overlap;i++)
+      window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
+# endif
+#endif
+   mode->window = window;
+
+   logN = (opus_int16*)opus_alloc(mode->nbEBands*sizeof(opus_int16));
+   if (logN==NULL)
+      goto failure;
+
+   for (i=0;i<mode->nbEBands;i++)
+      logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
+   mode->logN = logN;
+
+   compute_pulse_cache(mode, mode->maxLM);
+#ifdef ENABLE_QEXT
+   OPUS_CLEAR(&mode->qext_cache, 1);
+   if ( (mode->Fs == 48000 && (mode->shortMdctSize==120 || mode->shortMdctSize==90)) || (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) ) {
+      CELTMode dummy;
+      compute_qext_mode(&dummy, mode);
+      compute_pulse_cache(&dummy, dummy.maxLM);
+      OPUS_COPY(&mode->qext_cache, &dummy.cache, 1);
+   }
+#endif
+
+   if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts,
+           mode->maxLM, arch) == 0)
+      goto failure;
+
+   if (error)
+      *error = OPUS_OK;
+
+   return mode;
+failure:
+   if (error)
+      *error = OPUS_ALLOC_FAIL;
+   if (mode!=NULL)
+      opus_custom_mode_destroy(mode);
+   return NULL;
+#endif /* !CUSTOM_MODES */
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+void opus_custom_mode_destroy(CELTMode *mode)
+{
+   int arch = opus_select_arch();
+
+   if (mode == NULL)
+      return;
+#ifndef CUSTOM_MODES_ONLY
+   {
+     int i;
+     for (i=0;i<TOTAL_MODES;i++)
+     {
+        if (mode == static_mode_list[i])
+        {
+           return;
+        }
+     }
+   }
+#endif /* CUSTOM_MODES_ONLY */
+#ifdef CUSTOM_MODES
+#ifdef ENABLE_QEXT
+   if (mode->qext_cache.index) opus_free((opus_int16*)mode->qext_cache.index);
+   if (mode->qext_cache.bits) opus_free((unsigned char*)mode->qext_cache.bits);
+   if (mode->qext_cache.caps) opus_free((unsigned char*)mode->qext_cache.caps);
+#endif
+   opus_free((opus_int16*)mode->eBands);
+   opus_free((unsigned char*)mode->allocVectors);
+
+   opus_free((opus_val16*)mode->window);
+   opus_free((opus_int16*)mode->logN);
+
+   opus_free((opus_int16*)mode->cache.index);
+   opus_free((unsigned char*)mode->cache.bits);
+   opus_free((unsigned char*)mode->cache.caps);
+   clt_mdct_clear(&mode->mdct, arch);
+
+   opus_free((CELTMode *)mode);
+#else
+   (void)arch;
+   celt_assert(0);
+#endif
+}
+#endif
+
+#ifdef ENABLE_QEXT
+
+static const opus_int16 qext_eBands_180[] = {
+/* 20k  22k  24k  26k  28k  30k  32k  34k  36k  38k  40k  42k  44k  47k  48k */
+    74,  82,  90,  98, 106, 114, 122, 130, 138, 146, 154, 162, 168, 174, 180
+};
+
+static const opus_int16 qext_logN_180[] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21, 21, 21};
+
+/* Extra bands. */
+static const opus_int16 qext_eBands_240[] = {
+/* 20k  22k  24k  26k  28k  30k  32k  34k  36k  38k  40k  42k  44k  47k  48k */
+   100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240
+};
+
+static const opus_int16 qext_logN_240[] = {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27};
+
+void compute_qext_mode(CELTMode *qext, const CELTMode *m)
+{
+   OPUS_COPY(qext, m, 1);
+   if (m->shortMdctSize*48000 == 120*m->Fs) {
+      qext->eBands = qext_eBands_240;
+      qext->logN = qext_logN_240;
+   } else if (m->shortMdctSize*48000 == 90*m->Fs) {
+      qext->eBands = qext_eBands_180;
+      qext->logN = qext_logN_180;
+   } else {
+      celt_assert(0);
+   }
+   qext->nbEBands = qext->effEBands = NB_QEXT_BANDS;
+   while (qext->eBands[qext->effEBands] > qext->shortMdctSize)
+      qext->effEBands--;
+   qext->nbAllocVectors = 0;
+   qext->allocVectors = NULL;
+   OPUS_COPY(&qext->cache, &m->qext_cache, 1);
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/modes.h
new file mode 100644 (file)
index 0000000..06bfc65
--- /dev/null
@@ -0,0 +1,85 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MODES_H
+#define MODES_H
+
+#include "opus_types.h"
+#include "celt.h"
+#include "arch.h"
+#include "mdct.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#define MAX_PERIOD 1024
+
+#define DEC_PITCH_BUF_SIZE 2048
+
+typedef struct {
+   int size;
+   const opus_int16 *index;
+   const unsigned char *bits;
+   const unsigned char *caps;
+} PulseCache;
+
+/** Mode definition (opaque)
+ @brief Mode definition
+ */
+struct OpusCustomMode {
+   opus_int32 Fs;
+   int          overlap;
+
+   int          nbEBands;
+   int          effEBands;
+   opus_val16    preemph[4];
+   const opus_int16   *eBands;   /**< Definition for each "pseudo-critical band" */
+
+   int         maxLM;
+   int         nbShortMdcts;
+   int         shortMdctSize;
+
+   int          nbAllocVectors; /**< Number of lines in the matrix below */
+   const unsigned char   *allocVectors;   /**< Number of bits in each band for several rates */
+   const opus_int16 *logN;
+
+   const celt_coef *window;
+   mdct_lookup mdct;
+   PulseCache cache;
+#ifdef ENABLE_QEXT
+   PulseCache qext_cache;
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#define QEXT_PACKET_SIZE_CAP 3825
+#define NB_QEXT_BANDS 14
+void compute_qext_mode(CELTMode *qext, const CELTMode *m);
+#endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/os_support.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/os_support.h
new file mode 100644 (file)
index 0000000..48d742b
--- /dev/null
@@ -0,0 +1,98 @@
+/* Copyright (C) 2007 Jean-Marc Valin
+
+   File: os_support.h
+   This is the (tiny) OS abstraction layer. Aside from math.h, this is the
+   only place where system headers are allowed.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OS_SUPPORT_H
+#define OS_SUPPORT_H
+
+#ifdef CUSTOM_SUPPORT
+#  include "custom_support.h"
+#endif
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+/** Opus wrapper for malloc(). To do your own dynamic allocation replace this function, opus_realloc, and opus_free */
+#ifndef OVERRIDE_OPUS_ALLOC
+static OPUS_INLINE void *opus_alloc (size_t size)
+{
+   return malloc(size);
+}
+#endif
+
+#ifndef OVERRIDE_OPUS_REALLOC
+static OPUS_INLINE void *opus_realloc (void *ptr, size_t size)
+{
+   return realloc(ptr, size);
+}
+#endif
+
+/** Used only for non-threadsafe pseudostack.
+    If desired, this can always return the same area of memory rather than allocating a new one every time. */
+#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH
+static OPUS_INLINE void *opus_alloc_scratch (size_t size)
+{
+   /* Scratch space doesn't need to be cleared */
+   return opus_alloc(size);
+}
+#endif
+
+/** Opus wrapper for free(). To do your own dynamic allocation replace this function, opus_realloc, and opus_free */
+#ifndef OVERRIDE_OPUS_FREE
+static OPUS_INLINE void opus_free (void *ptr)
+{
+   free(ptr);
+}
+#endif
+
+/** Copy n elements from src to dst. The 0* term provides compile-time type checking  */
+#ifndef OVERRIDE_OPUS_COPY
+#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Copy n elements from src to dst, allowing overlapping regions. The 0* term
+    provides compile-time type checking */
+#ifndef OVERRIDE_OPUS_MOVE
+#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Set n elements of dst to zero */
+#ifndef OVERRIDE_OPUS_CLEAR
+#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst))))
+#endif
+
+/*#ifdef __GNUC__
+#pragma GCC poison printf sprintf
+#pragma GCC poison malloc free realloc calloc
+#endif*/
+
+#endif /* OS_SUPPORT_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.c
new file mode 100644 (file)
index 0000000..fe3b0bd
--- /dev/null
@@ -0,0 +1,560 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/**
+   @file pitch.c
+   @brief Pitch analysis
+ */
+
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pitch.h"
+#include "os_support.h"
+#include "modes.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "celt_lpc.h"
+
+static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
+                            int max_pitch, int *best_pitch
+#ifdef FIXED_POINT
+                            , int yshift, opus_val32 maxcorr
+#endif
+                            )
+{
+   int i, j;
+   opus_val32 Syy=1;
+   opus_val16 best_num[2];
+   opus_val32 best_den[2];
+#ifdef FIXED_POINT
+   int xshift;
+
+   xshift = celt_ilog2(maxcorr)-14;
+#endif
+
+   best_num[0] = -1;
+   best_num[1] = -1;
+   best_den[0] = 0;
+   best_den[1] = 0;
+   best_pitch[0] = 0;
+   best_pitch[1] = 1;
+   for (j=0;j<len;j++)
+      Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
+   for (i=0;i<max_pitch;i++)
+   {
+      if (xcorr[i]>0)
+      {
+         opus_val16 num;
+         opus_val32 xcorr16;
+         xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
+#ifndef FIXED_POINT
+         /* Considering the range of xcorr16, this should avoid both underflows
+            and overflows (inf) when squaring xcorr16 */
+         xcorr16 *= 1e-12f;
+#endif
+         num = MULT16_16_Q15(xcorr16,xcorr16);
+         if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
+         {
+            if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
+            {
+               best_num[1] = best_num[0];
+               best_den[1] = best_den[0];
+               best_pitch[1] = best_pitch[0];
+               best_num[0] = num;
+               best_den[0] = Syy;
+               best_pitch[0] = i;
+            } else {
+               best_num[1] = num;
+               best_den[1] = Syy;
+               best_pitch[1] = i;
+            }
+         }
+      }
+      Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
+      Syy = MAX32(1, Syy);
+   }
+}
+
+static void celt_fir5(opus_val16 *x,
+         const opus_val16 *num,
+         int N)
+{
+   int i;
+   opus_val16 num0, num1, num2, num3, num4;
+   opus_val32 mem0, mem1, mem2, mem3, mem4;
+   num0=num[0];
+   num1=num[1];
+   num2=num[2];
+   num3=num[3];
+   num4=num[4];
+   mem0=0;
+   mem1=0;
+   mem2=0;
+   mem3=0;
+   mem4=0;
+   for (i=0;i<N;i++)
+   {
+      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
+      sum = MAC16_16(sum,num0,mem0);
+      sum = MAC16_16(sum,num1,mem1);
+      sum = MAC16_16(sum,num2,mem2);
+      sum = MAC16_16(sum,num3,mem3);
+      sum = MAC16_16(sum,num4,mem4);
+      mem4 = mem3;
+      mem3 = mem2;
+      mem2 = mem1;
+      mem1 = mem0;
+      mem0 = x[i];
+      x[i] = ROUND16(sum, SIG_SHIFT);
+   }
+}
+
+
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
+      int len, int C, int factor, int arch)
+{
+   int i;
+   opus_val32 ac[5];
+   opus_val16 tmp=Q15ONE;
+   opus_val16 lpc[4];
+   opus_val16 lpc2[5];
+   opus_val16 c1 = QCONST16(.8f,15);
+   int offset;
+#ifdef FIXED_POINT
+   int shift;
+   opus_val32 maxabs;
+#endif
+   offset = factor/2;
+#ifdef FIXED_POINT
+   maxabs = celt_maxabs32(x[0], len*factor);
+   if (C==2)
+   {
+      opus_val32 maxabs_1 = celt_maxabs32(x[1], len*factor);
+      maxabs = MAX32(maxabs, maxabs_1);
+   }
+   if (maxabs<1)
+      maxabs=1;
+   shift = celt_ilog2(maxabs)-10;
+   if (shift<0)
+      shift=0;
+   if (C==2)
+      shift++;
+   for (i=1;i<len;i++)
+      x_lp[i] = SHR32(x[0][(factor*i-offset)], shift+2) + SHR32(x[0][(factor*i+offset)], shift+2) + SHR32(x[0][factor*i], shift+1);
+   x_lp[0] = SHR32(x[0][offset], shift+2) + SHR32(x[0][0], shift+1);
+   if (C==2)
+   {
+      for (i=1;i<len;i++)
+         x_lp[i] += SHR32(x[1][(factor*i-offset)], shift+2) + SHR32(x[1][(factor*i+offset)], shift+2) + SHR32(x[1][factor*i], shift+1);
+      x_lp[0] += SHR32(x[1][offset], shift+2) + SHR32(x[1][0], shift+1);
+   }
+#else
+   for (i=1;i<len;i++)
+      x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i];
+   x_lp[0] = .25f*x[0][offset] + .5f*x[0][0];
+   if (C==2)
+   {
+      for (i=1;i<len;i++)
+         x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i];
+      x_lp[0] += .25f*x[1][offset] + .5f*x[1][0];
+   }
+#endif
+   _celt_autocorr(x_lp, ac, NULL, 0,
+                  4, len, arch);
+
+   /* Noise floor -40 dB */
+#ifdef FIXED_POINT
+   ac[0] += SHR32(ac[0],13);
+#else
+   ac[0] *= 1.0001f;
+#endif
+   /* Lag windowing */
+   for (i=1;i<=4;i++)
+   {
+      /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+#ifdef FIXED_POINT
+      ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+#else
+      ac[i] -= ac[i]*(.008f*i)*(.008f*i);
+#endif
+   }
+
+   _celt_lpc(lpc, ac, 4);
+   for (i=0;i<4;i++)
+   {
+      tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
+      lpc[i] = MULT16_16_Q15(lpc[i], tmp);
+   }
+   /* Add a zero */
+   lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
+   lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
+   lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
+   lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
+   lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
+   celt_fir5(x_lp, lpc2, len);
+}
+
+/* Pure C implementation. */
+#ifdef FIXED_POINT
+opus_val32
+#else
+void
+#endif
+celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+      opus_val32 *xcorr, int len, int max_pitch, int arch)
+{
+
+#if 0 /* This is a simple version of the pitch correlation that should work
+         well on DSPs like Blackfin and TI C5x/C6x */
+   int i, j;
+#ifdef FIXED_POINT
+   opus_val32 maxcorr=1;
+#endif
+#if !defined(OVERRIDE_PITCH_XCORR)
+   (void)arch;
+#endif
+   for (i=0;i<max_pitch;i++)
+   {
+      opus_val32 sum = 0;
+      for (j=0;j<len;j++)
+         sum = MAC16_16(sum, _x[j], _y[i+j]);
+      xcorr[i] = sum;
+#ifdef FIXED_POINT
+      maxcorr = MAX32(maxcorr, sum);
+#endif
+   }
+#ifdef FIXED_POINT
+   return maxcorr;
+#endif
+
+#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
+   int i;
+   /*The EDSP version requires that max_pitch is at least 1, and that _x is
+      32-bit aligned.
+     Since it's hard to put asserts in assembly, put them here.*/
+#ifdef FIXED_POINT
+   opus_val32 maxcorr=1;
+#endif
+   celt_assert(max_pitch>0);
+   celt_sig_assert(((size_t)_x&3)==0);
+   for (i=0;i<max_pitch-3;i+=4)
+   {
+      opus_val32 sum[4]={0,0,0,0};
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+      {
+         opus_val32 sum_c[4]={0,0,0,0};
+         xcorr_kernel_c(_x, _y+i, sum_c, len);
+#endif
+         xcorr_kernel(_x, _y+i, sum, len, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+      }
+#endif
+      xcorr[i]=sum[0];
+      xcorr[i+1]=sum[1];
+      xcorr[i+2]=sum[2];
+      xcorr[i+3]=sum[3];
+#ifdef FIXED_POINT
+      sum[0] = MAX32(sum[0], sum[1]);
+      sum[2] = MAX32(sum[2], sum[3]);
+      sum[0] = MAX32(sum[0], sum[2]);
+      maxcorr = MAX32(maxcorr, sum[0]);
+#endif
+   }
+   /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
+   for (;i<max_pitch;i++)
+   {
+      opus_val32 sum;
+      sum = celt_inner_prod(_x, _y+i, len, arch);
+      xcorr[i] = sum;
+#ifdef FIXED_POINT
+      maxcorr = MAX32(maxcorr, sum);
+#endif
+   }
+#ifdef FIXED_POINT
+   return maxcorr;
+#endif
+#endif
+}
+
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
+                  int len, int max_pitch, int *pitch, int arch)
+{
+   int i, j;
+   int lag;
+   int best_pitch[2]={0,0};
+   VARDECL(opus_val16, x_lp4);
+   VARDECL(opus_val16, y_lp4);
+   VARDECL(opus_val32, xcorr);
+#ifdef FIXED_POINT
+   opus_val32 maxcorr;
+   opus_val32 xmax, ymax;
+   int shift=0;
+#endif
+   int offset;
+
+   SAVE_STACK;
+
+   celt_assert(len>0);
+   celt_assert(max_pitch>0);
+   lag = len+max_pitch;
+
+   ALLOC(x_lp4, len>>2, opus_val16);
+   ALLOC(y_lp4, lag>>2, opus_val16);
+   ALLOC(xcorr, max_pitch>>1, opus_val32);
+
+   /* Downsample by 2 again */
+   for (j=0;j<len>>2;j++)
+      x_lp4[j] = x_lp[2*j];
+   for (j=0;j<lag>>2;j++)
+      y_lp4[j] = y[2*j];
+
+#ifdef FIXED_POINT
+   xmax = celt_maxabs16(x_lp4, len>>2);
+   ymax = celt_maxabs16(y_lp4, lag>>2);
+   shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax))) - 14 + celt_ilog2(len)/2;
+   if (shift>0)
+   {
+      for (j=0;j<len>>2;j++)
+         x_lp4[j] = SHR16(x_lp4[j], shift);
+      for (j=0;j<lag>>2;j++)
+         y_lp4[j] = SHR16(y_lp4[j], shift);
+      /* Use double the shift for a MAC */
+      shift *= 2;
+   } else {
+      shift = 0;
+   }
+#endif
+
+   /* Coarse search with 4x decimation */
+
+#ifdef FIXED_POINT
+   maxcorr =
+#endif
+   celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
+
+   find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
+#ifdef FIXED_POINT
+                   , 0, maxcorr
+#endif
+                   );
+
+   /* Finer search with 2x decimation */
+#ifdef FIXED_POINT
+   maxcorr=1;
+#endif
+   for (i=0;i<max_pitch>>1;i++)
+   {
+      opus_val32 sum;
+      xcorr[i] = 0;
+      if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
+         continue;
+#ifdef FIXED_POINT
+      sum = 0;
+      for (j=0;j<len>>1;j++)
+         sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
+#else
+      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
+#endif
+      xcorr[i] = MAX32(-1, sum);
+#ifdef FIXED_POINT
+      maxcorr = MAX32(maxcorr, sum);
+#endif
+   }
+   find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
+#ifdef FIXED_POINT
+                   , shift+1, maxcorr
+#endif
+                   );
+
+   /* Refine by pseudo-interpolation */
+   if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
+   {
+      opus_val32 a, b, c;
+      a = xcorr[best_pitch[0]-1];
+      b = xcorr[best_pitch[0]];
+      c = xcorr[best_pitch[0]+1];
+      if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
+         offset = 1;
+      else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
+         offset = -1;
+      else
+         offset = 0;
+   } else {
+      offset = 0;
+   }
+   *pitch = 2*best_pitch[0]-offset;
+
+   RESTORE_STACK;
+}
+
+#ifdef FIXED_POINT
+static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
+{
+   opus_val32 x2y2;
+   int sx, sy, shift;
+   opus_val32 g;
+   opus_val16 den;
+   if (xy == 0 || xx == 0 || yy == 0)
+      return 0;
+   sx = celt_ilog2(xx)-14;
+   sy = celt_ilog2(yy)-14;
+   shift = sx + sy;
+   x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
+   if (shift & 1) {
+      if (x2y2 < 32768)
+      {
+         x2y2 <<= 1;
+         shift--;
+      } else {
+         x2y2 >>= 1;
+         shift++;
+      }
+   }
+   den = celt_rsqrt_norm(x2y2);
+   g = MULT16_32_Q15(den, xy);
+   g = VSHR32(g, (shift>>1)-1);
+   return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE)));
+}
+#else
+static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
+{
+   return xy/celt_sqrt(1+xx*yy);
+}
+#endif
+
+static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
+opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
+      int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
+{
+   int k, i, T, T0;
+   opus_val16 g, g0;
+   opus_val16 pg;
+   opus_val32 xy,xx,yy,xy2;
+   opus_val32 xcorr[3];
+   opus_val32 best_xy, best_yy;
+   int offset;
+   int minperiod0;
+   VARDECL(opus_val32, yy_lookup);
+   SAVE_STACK;
+
+   minperiod0 = minperiod;
+   maxperiod /= 2;
+   minperiod /= 2;
+   *T0_ /= 2;
+   prev_period /= 2;
+   N /= 2;
+   x += maxperiod;
+   if (*T0_>=maxperiod)
+      *T0_=maxperiod-1;
+
+   T = T0 = *T0_;
+   ALLOC(yy_lookup, maxperiod+1, opus_val32);
+   dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
+   yy_lookup[0] = xx;
+   yy=xx;
+   for (i=1;i<=maxperiod;i++)
+   {
+      yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
+      yy_lookup[i] = MAX32(0, yy);
+   }
+   yy = yy_lookup[T0];
+   best_xy = xy;
+   best_yy = yy;
+   g = g0 = compute_pitch_gain(xy, xx, yy);
+   /* Look for any pitch at T/k */
+   for (k=2;k<=15;k++)
+   {
+      int T1, T1b;
+      opus_val16 g1;
+      opus_val16 cont=0;
+      opus_val16 thresh;
+      T1 = celt_udiv(2*T0+k, 2*k);
+      if (T1 < minperiod)
+         break;
+      /* Look for another strong correlation at T1b */
+      if (k==2)
+      {
+         if (T1+T0>maxperiod)
+            T1b = T0;
+         else
+            T1b = T0+T1;
+      } else
+      {
+         T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
+      }
+      dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
+      xy = HALF32(xy + xy2);
+      yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
+      g1 = compute_pitch_gain(xy, xx, yy);
+      if (abs(T1-prev_period)<=1)
+         cont = prev_gain;
+      else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
+         cont = HALF16(prev_gain);
+      else
+         cont = 0;
+      thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
+      /* Bias against very high pitch (very short period) to avoid false-positives
+         due to short-term correlation */
+      if (T1<3*minperiod)
+         thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
+      else if (T1<2*minperiod)
+         thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
+      if (g1 > thresh)
+      {
+         best_xy = xy;
+         best_yy = yy;
+         T = T1;
+         g = g1;
+      }
+   }
+   best_xy = MAX32(0, best_xy);
+   if (best_yy <= best_xy)
+      pg = Q15ONE;
+   else
+      pg = SHR32(frac_div32(best_xy,best_yy+1),16);
+
+   for (k=0;k<3;k++)
+      xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
+   if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
+      offset = 1;
+   else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
+      offset = -1;
+   else
+      offset = 0;
+   if (pg > g)
+      pg = g;
+   *T0_ = 2*T+offset;
+
+   if (*T0_<minperiod0)
+      *T0_=minperiod0;
+   RESTORE_STACK;
+   return pg;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/pitch.h
new file mode 100644 (file)
index 0000000..e5eecdd
--- /dev/null
@@ -0,0 +1,203 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/**
+   @file pitch.h
+   @brief Pitch analysis
+ */
+
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PITCH_H
+#define PITCH_H
+
+#include "modes.h"
+#include "cpu_support.h"
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)) \
+  || ((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT))
+#include "x86/pitch_sse.h"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/pitch_mipsr1.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+# include "arm/pitch_arm.h"
+#endif
+
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
+      int len, int C, int factor, int arch);
+
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
+                  int len, int max_pitch, int *pitch, int arch);
+
+opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
+      int N, int *T0, int prev_period, opus_val16 prev_gain, int arch);
+
+
+/* OPT: This is the kernel you really want to optimize. It gets used a lot
+   by the prefilter and by the PLC. */
+static OPUS_INLINE void xcorr_kernel_c(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
+{
+   int j;
+   opus_val16 y_0, y_1, y_2, y_3;
+   celt_assert(len>=3);
+   y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */
+   y_0=*y++;
+   y_1=*y++;
+   y_2=*y++;
+   for (j=0;j<len-3;j+=4)
+   {
+      opus_val16 tmp;
+      tmp = *x++;
+      y_3=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_0);
+      sum[1] = MAC16_16(sum[1],tmp,y_1);
+      sum[2] = MAC16_16(sum[2],tmp,y_2);
+      sum[3] = MAC16_16(sum[3],tmp,y_3);
+      tmp=*x++;
+      y_0=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_1);
+      sum[1] = MAC16_16(sum[1],tmp,y_2);
+      sum[2] = MAC16_16(sum[2],tmp,y_3);
+      sum[3] = MAC16_16(sum[3],tmp,y_0);
+      tmp=*x++;
+      y_1=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_2);
+      sum[1] = MAC16_16(sum[1],tmp,y_3);
+      sum[2] = MAC16_16(sum[2],tmp,y_0);
+      sum[3] = MAC16_16(sum[3],tmp,y_1);
+      tmp=*x++;
+      y_2=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_3);
+      sum[1] = MAC16_16(sum[1],tmp,y_0);
+      sum[2] = MAC16_16(sum[2],tmp,y_1);
+      sum[3] = MAC16_16(sum[3],tmp,y_2);
+   }
+   if (j++<len)
+   {
+      opus_val16 tmp = *x++;
+      y_3=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_0);
+      sum[1] = MAC16_16(sum[1],tmp,y_1);
+      sum[2] = MAC16_16(sum[2],tmp,y_2);
+      sum[3] = MAC16_16(sum[3],tmp,y_3);
+   }
+   if (j++<len)
+   {
+      opus_val16 tmp=*x++;
+      y_0=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_1);
+      sum[1] = MAC16_16(sum[1],tmp,y_2);
+      sum[2] = MAC16_16(sum[2],tmp,y_3);
+      sum[3] = MAC16_16(sum[3],tmp,y_0);
+   }
+   if (j<len)
+   {
+      opus_val16 tmp=*x++;
+      y_1=*y++;
+      sum[0] = MAC16_16(sum[0],tmp,y_2);
+      sum[1] = MAC16_16(sum[1],tmp,y_3);
+      sum[2] = MAC16_16(sum[2],tmp,y_0);
+      sum[3] = MAC16_16(sum[3],tmp,y_1);
+   }
+}
+
+#ifndef OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+    ((void)(arch),xcorr_kernel_c(x, y, sum, len))
+#endif /* OVERRIDE_XCORR_KERNEL */
+
+
+static OPUS_INLINE void dual_inner_prod_c(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+   int i;
+   opus_val32 xy01=0;
+   opus_val32 xy02=0;
+   for (i=0;i<N;i++)
+   {
+      xy01 = MAC16_16(xy01, x[i], y01[i]);
+      xy02 = MAC16_16(xy02, x[i], y02[i]);
+   }
+   *xy1 = xy01;
+   *xy2 = xy02;
+}
+
+#ifndef OVERRIDE_DUAL_INNER_PROD
+# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+    ((void)(arch),dual_inner_prod_c(x, y01, y02, N, xy1, xy2))
+#endif
+
+/*We make sure a C version is always available for cases where the overhead of
+  vectorization and passing around an arch flag aren't worth it.*/
+static OPUS_INLINE opus_val32 celt_inner_prod_c(const opus_val16 *x,
+      const opus_val16 *y, int N)
+{
+   int i;
+   opus_val32 xy=0;
+   for (i=0;i<N;i++)
+      xy = MAC16_16(xy, x[i], y[i]);
+   return xy;
+}
+
+#if !defined(OVERRIDE_CELT_INNER_PROD)
+# define celt_inner_prod(x, y, N, arch) \
+    ((void)(arch),celt_inner_prod_c(x, y, N))
+#endif
+
+#ifdef NON_STATIC_COMB_FILTER_CONST_C
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+     opus_val16 g10, opus_val16 g11, opus_val16 g12);
+#endif
+
+
+#ifdef FIXED_POINT
+opus_val32
+#else
+void
+#endif
+celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+      opus_val32 *xcorr, int len, int max_pitch, int arch);
+
+#ifndef OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_c
+#endif
+
+#ifdef NON_STATIC_COMB_FILTER_CONST_C
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+                         opus_val16 g10, opus_val16 g11, opus_val16 g12);
+#endif
+
+#ifndef OVERRIDE_COMB_FILTER_CONST
+# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+    ((void)(arch),comb_filter_const_c(y, x, T, N, g10, g11, g12))
+#endif
+
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.c
new file mode 100644 (file)
index 0000000..4bb1e28
--- /dev/null
@@ -0,0 +1,572 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "quant_bands.h"
+#include "laplace.h"
+#include <math.h>
+#include "os_support.h"
+#include "arch.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+#include "rate.h"
+
+#ifdef FIXED_POINT
+/* Mean energy in each band quantized in Q4 */
+const signed char eMeans[25] = {
+      103,100, 92, 85, 81,
+       77, 72, 70, 78, 75,
+       73, 71, 78, 74, 69,
+       72, 70, 74, 76, 71,
+       60, 60, 60, 60, 60
+};
+#else
+/* Mean energy in each band quantized in Q4 and converted back to float */
+const opus_val16 eMeans[25] = {
+      6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f,
+      4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f,
+      4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f,
+      4.500000f, 4.375000f, 4.625000f, 4.750000f, 4.437500f,
+      3.750000f, 3.750000f, 3.750000f, 3.750000f, 3.750000f
+};
+#endif
+/* prediction coefficients: 0.9, 0.8, 0.65, 0.5 */
+#ifdef FIXED_POINT
+static const opus_val16 pred_coef[4] = {29440, 26112, 21248, 16384};
+static const opus_val16 beta_coef[4] = {30147, 22282, 12124, 6554};
+static const opus_val16 beta_intra = 4915;
+#else
+static const opus_val16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.};
+static const opus_val16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.};
+static const opus_val16 beta_intra = 4915/32768.;
+#endif
+
+/*Parameters of the Laplace-like probability models used for the coarse energy.
+  There is one pair of parameters for each frame size, prediction type
+   (inter/intra), and band number.
+  The first number of each pair is the probability of 0, and the second is the
+   decay rate, both in Q8 precision.*/
+static const unsigned char e_prob_model[4][2][42] = {
+   /*120 sample frames.*/
+   {
+      /*Inter*/
+      {
+          72, 127,  65, 129,  66, 128,  65, 128,  64, 128,  62, 128,  64, 128,
+          64, 128,  92,  78,  92,  79,  92,  78,  90,  79, 116,  41, 115,  40,
+         114,  40, 132,  26, 132,  26, 145,  17, 161,  12, 176,  10, 177,  11
+      },
+      /*Intra*/
+      {
+          24, 179,  48, 138,  54, 135,  54, 132,  53, 134,  56, 133,  55, 132,
+          55, 132,  61, 114,  70,  96,  74,  88,  75,  88,  87,  74,  89,  66,
+          91,  67, 100,  59, 108,  50, 120,  40, 122,  37,  97,  43,  78,  50
+      }
+   },
+   /*240 sample frames.*/
+   {
+      /*Inter*/
+      {
+          83,  78,  84,  81,  88,  75,  86,  74,  87,  71,  90,  73,  93,  74,
+          93,  74, 109,  40, 114,  36, 117,  34, 117,  34, 143,  17, 145,  18,
+         146,  19, 162,  12, 165,  10, 178,   7, 189,   6, 190,   8, 177,   9
+      },
+      /*Intra*/
+      {
+          23, 178,  54, 115,  63, 102,  66,  98,  69,  99,  74,  89,  71,  91,
+          73,  91,  78,  89,  86,  80,  92,  66,  93,  64, 102,  59, 103,  60,
+         104,  60, 117,  52, 123,  44, 138,  35, 133,  31,  97,  38,  77,  45
+      }
+   },
+   /*480 sample frames.*/
+   {
+      /*Inter*/
+      {
+          61,  90,  93,  60, 105,  42, 107,  41, 110,  45, 116,  38, 113,  38,
+         112,  38, 124,  26, 132,  27, 136,  19, 140,  20, 155,  14, 159,  16,
+         158,  18, 170,  13, 177,  10, 187,   8, 192,   6, 175,   9, 159,  10
+      },
+      /*Intra*/
+      {
+          21, 178,  59, 110,  71,  86,  75,  85,  84,  83,  91,  66,  88,  73,
+          87,  72,  92,  75,  98,  72, 105,  58, 107,  54, 115,  52, 114,  55,
+         112,  56, 129,  51, 132,  40, 150,  33, 140,  29,  98,  35,  77,  42
+      }
+   },
+   /*960 sample frames.*/
+   {
+      /*Inter*/
+      {
+          42, 121,  96,  66, 108,  43, 111,  40, 117,  44, 123,  32, 120,  36,
+         119,  33, 127,  33, 134,  34, 139,  21, 147,  23, 152,  20, 158,  25,
+         154,  26, 166,  21, 173,  16, 184,  13, 184,  10, 150,  13, 139,  15
+      },
+      /*Intra*/
+      {
+          22, 178,  63, 114,  74,  82,  84,  83,  92,  82, 103,  62,  96,  72,
+          96,  67, 101,  73, 107,  72, 113,  55, 118,  52, 125,  52, 118,  52,
+         117,  55, 135,  49, 137,  39, 157,  32, 145,  29,  97,  33,  77,  40
+      }
+   }
+};
+
+static const unsigned char small_energy_icdf[3]={2,1,0};
+
+static opus_val32 loss_distortion(const celt_glog *eBands, celt_glog *oldEBands, int start, int end, int len, int C)
+{
+   int c, i;
+   opus_val32 dist = 0;
+   c=0; do {
+      for (i=start;i<end;i++)
+      {
+         celt_glog d = PSHR32(SUB32(eBands[i+c*len], oldEBands[i+c*len]), DB_SHIFT-7);
+         dist = MAC16_16(dist, d,d);
+      }
+   } while (++c<C);
+   return MIN32(200,SHR32(dist,14));
+}
+
+static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
+      const celt_glog *eBands, celt_glog *oldEBands,
+      opus_int32 budget, opus_int32 tell,
+      const unsigned char *prob_model, celt_glog *error, ec_enc *enc,
+      int C, int LM, int intra, celt_glog max_decay, int lfe)
+{
+   int i, c;
+   int badness = 0;
+   opus_val32 prev[2] = {0,0};
+   opus_val16 coef;
+   opus_val16 beta;
+
+   if (tell+3 <= budget)
+      ec_enc_bit_logp(enc, intra, 3);
+   if (intra)
+   {
+      coef = 0;
+      beta = beta_intra;
+   } else {
+      beta = beta_coef[LM];
+      coef = pred_coef[LM];
+   }
+
+   /* Encode at a fixed coarse resolution */
+   for (i=start;i<end;i++)
+   {
+      c=0;
+      do {
+         int bits_left;
+         int qi, qi0;
+         opus_val32 q;
+         celt_glog x;
+         opus_val32 f, tmp;
+         celt_glog oldE;
+         celt_glog decay_bound;
+         x = eBands[i+c*m->nbEBands];
+         oldE = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
+#ifdef FIXED_POINT
+         f = x - MULT16_32_Q15(coef,oldE) - prev[c];
+         /* Rounding to nearest integer here is really important! */
+         qi = (f+QCONST32(.5f,DB_SHIFT))>>DB_SHIFT;
+         decay_bound = MAXG(-GCONST(28.f), SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay));
+#else
+         f = x-coef*oldE-prev[c];
+         /* Rounding to nearest integer here is really important! */
+         qi = (int)floor(.5f+f);
+         decay_bound = MAXG(-GCONST(28.f), oldEBands[i+c*m->nbEBands]) - max_decay;
+#endif
+         /* Prevent the energy from going down too quickly (e.g. for bands
+            that have just one bin) */
+         if (qi < 0 && x < decay_bound)
+         {
+            qi += (int)SHR32(SUB32(decay_bound,x), DB_SHIFT);
+            if (qi > 0)
+               qi = 0;
+         }
+         qi0 = qi;
+         /* If we don't have enough bits to encode all the energy, just assume
+             something safe. */
+         tell = ec_tell(enc);
+         bits_left = budget-tell-3*C*(end-i);
+         if (i!=start && bits_left < 30)
+         {
+            if (bits_left < 24)
+               qi = IMIN(1, qi);
+            if (bits_left < 16)
+               qi = IMAX(-1, qi);
+         }
+         if (lfe && i>=2)
+            qi = IMIN(qi, 0);
+         if (budget-tell >= 15)
+         {
+            int pi;
+            pi = 2*IMIN(i,20);
+            ec_laplace_encode(enc, &qi,
+                  prob_model[pi]<<7, prob_model[pi+1]<<6);
+         }
+         else if(budget-tell >= 2)
+         {
+            qi = IMAX(-1, IMIN(qi, 1));
+            ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2);
+         }
+         else if(budget-tell >= 1)
+         {
+            qi = IMIN(0, qi);
+            ec_enc_bit_logp(enc, -qi, 1);
+         }
+         else
+            qi = -1;
+         error[i+c*m->nbEBands] = f - SHL32(qi,DB_SHIFT);
+         badness += abs(qi0-qi);
+         q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
+
+         tmp = MULT16_32_Q15(coef,oldE) + prev[c] + q;
+#ifdef FIXED_POINT
+         tmp = MAX32(-GCONST(28.f), tmp);
+#endif
+         oldEBands[i+c*m->nbEBands] = tmp;
+         prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
+      } while (++c < C);
+   }
+   return lfe ? 0 : badness;
+}
+
+void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
+      const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
+      celt_glog *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
+      int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe)
+{
+   int intra;
+   celt_glog max_decay;
+   VARDECL(celt_glog, oldEBands_intra);
+   VARDECL(celt_glog, error_intra);
+   ec_enc enc_start_state;
+   opus_uint32 tell;
+   int badness1=0;
+   opus_int32 intra_bias;
+   opus_val32 new_distortion;
+   SAVE_STACK;
+
+   intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
+   intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512));
+   new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C);
+
+   tell = ec_tell(enc);
+   if (tell+3 > budget)
+      two_pass = intra = 0;
+
+   max_decay = GCONST(16.f);
+   if (end-start>10)
+   {
+#ifdef FIXED_POINT
+      max_decay = SHL32(MIN32(SHR32(max_decay,DB_SHIFT-3), EXTEND32(nbAvailableBytes)),DB_SHIFT-3);
+#else
+      max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
+#endif
+   }
+   if (lfe)
+      max_decay = GCONST(3.f);
+   enc_start_state = *enc;
+
+   ALLOC(oldEBands_intra, C*m->nbEBands, celt_glog);
+   ALLOC(error_intra, C*m->nbEBands, celt_glog);
+   OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
+
+   if (two_pass || intra)
+   {
+      badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
+            tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe);
+   }
+
+   if (!intra)
+   {
+      unsigned char *intra_buf;
+      ec_enc enc_intra_state;
+      opus_int32 tell_intra;
+      opus_uint32 nstart_bytes;
+      opus_uint32 nintra_bytes;
+      opus_uint32 save_bytes;
+      int badness2;
+      VARDECL(unsigned char, intra_bits);
+
+      tell_intra = ec_tell_frac(enc);
+
+      enc_intra_state = *enc;
+
+      nstart_bytes = ec_range_bytes(&enc_start_state);
+      nintra_bytes = ec_range_bytes(&enc_intra_state);
+      intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes;
+      save_bytes = nintra_bytes-nstart_bytes;
+      if (save_bytes == 0)
+         save_bytes = ALLOC_NONE;
+      ALLOC(intra_bits, save_bytes, unsigned char);
+      /* Copy bits from intra bit-stream */
+      OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes);
+
+      *enc = enc_start_state;
+
+      badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
+            tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe);
+
+      if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
+      {
+         *enc = enc_intra_state;
+         /* Copy intra bits to bit-stream */
+         OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes);
+         OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
+         OPUS_COPY(error, error_intra, C*m->nbEBands);
+         intra = 1;
+      }
+   } else {
+      OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
+      OPUS_COPY(error, error_intra, C*m->nbEBands);
+   }
+
+   if (intra)
+      *delayedIntra = new_distortion;
+   else
+      *delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra),
+            new_distortion);
+
+   RESTORE_STACK;
+}
+
+void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *prev_quant, int *extra_quant, ec_enc *enc, int C)
+{
+   int i, c;
+   /* Encode finer resolution */
+   for (i=start;i<end;i++)
+   {
+      opus_int16 extra, prev;
+      extra = 1<<extra_quant[i];
+      if (extra_quant[i] <= 0)
+         continue;
+      if (ec_tell(enc)+C*extra_quant[i] > (opus_int32)enc->storage*8) continue;
+      prev = (prev_quant!=NULL) ? prev_quant[i] : 0;
+      c=0;
+      do {
+         int q2;
+         celt_glog offset;
+#ifdef FIXED_POINT
+         /* Has to be without rounding */
+         q2 = VSHR32(ADD32(error[i+c*m->nbEBands], SHR32(GCONST(.5f), prev)), DB_SHIFT-extra_quant[i]-prev);
+#else
+         q2 = (int)floor((error[i+c*m->nbEBands]*(1<<prev)+.5f)*extra);
+#endif
+         if (q2 > extra-1)
+            q2 = extra-1;
+         if (q2<0)
+            q2 = 0;
+         ec_enc_bits(enc, q2, extra_quant[i]);
+#ifdef FIXED_POINT
+         offset = SUB32(VSHR32(2*q2+1, extra_quant[i]-DB_SHIFT+1), GCONST(.5f));
+         offset = SHR32(offset, prev);
+#else
+         offset = (q2+.5f)*(1<<(14-extra_quant[i]))*(1.f/16384) - .5f;
+         offset *= (1<<(14-prev))*(1.f/16384);
+#endif
+         oldEBands[i+c*m->nbEBands] += offset;
+         error[i+c*m->nbEBands] -= offset;
+         /*printf ("%f ", error[i] - offset);*/
+      } while (++c < C);
+   }
+}
+
+void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
+{
+   int i, prio, c;
+
+   /* Use up the remaining bits */
+   for (prio=0;prio<2;prio++)
+   {
+      for (i=start;i<end && bits_left>=C ;i++)
+      {
+         if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
+            continue;
+         c=0;
+         do {
+            int q2;
+            celt_glog offset;
+            q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
+            ec_enc_bits(enc, q2, 1);
+#ifdef FIXED_POINT
+            offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
+#else
+            offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+            if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset;
+            error[i+c*m->nbEBands] -= offset;
+            bits_left--;
+         } while (++c < C);
+      }
+   }
+}
+
+void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM)
+{
+   const unsigned char *prob_model = e_prob_model[LM][intra];
+   int i, c;
+   opus_val64 prev[2] = {0, 0};
+   opus_val16 coef;
+   opus_val16 beta;
+   opus_int32 budget;
+   opus_int32 tell;
+
+   if (intra)
+   {
+      coef = 0;
+      beta = beta_intra;
+   } else {
+      beta = beta_coef[LM];
+      coef = pred_coef[LM];
+   }
+
+   budget = dec->storage*8;
+
+   /* Decode at a fixed coarse resolution */
+   for (i=start;i<end;i++)
+   {
+      c=0;
+      do {
+         int qi;
+         opus_val32 q;
+         opus_val32 tmp;
+         /* It would be better to express this invariant as a
+            test on C at function entry, but that isn't enough
+            to make the static analyzer happy. */
+         celt_sig_assert(c<2);
+         tell = ec_tell(dec);
+         if(budget-tell>=15)
+         {
+            int pi;
+            pi = 2*IMIN(i,20);
+            qi = ec_laplace_decode(dec,
+                  prob_model[pi]<<7, prob_model[pi+1]<<6);
+         }
+         else if(budget-tell>=2)
+         {
+            qi = ec_dec_icdf(dec, small_energy_icdf, 2);
+            qi = (qi>>1)^-(qi&1);
+         }
+         else if(budget-tell>=1)
+         {
+            qi = -ec_dec_bit_logp(dec, 1);
+         }
+         else
+            qi = -1;
+         q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
+
+         oldEBands[i+c*m->nbEBands] = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
+         tmp = MULT16_32_Q15(coef,oldEBands[i+c*m->nbEBands]) + prev[c] + q;
+#ifdef FIXED_POINT
+         tmp = MIN32(GCONST(28.f), MAX32(-GCONST(28.f), tmp));
+#endif
+         oldEBands[i+c*m->nbEBands] = tmp;
+         prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
+      } while (++c < C);
+   }
+}
+
+void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *prev_quant, int *extra_quant, ec_dec *dec, int C)
+{
+   int i, c;
+   /* Decode finer resolution */
+   for (i=start;i<end;i++)
+   {
+      opus_int16 extra, prev;
+      extra = extra_quant[i];
+      if (extra_quant[i] <= 0)
+         continue;
+      if (ec_tell(dec)+C*extra_quant[i] > (opus_int32)dec->storage*8) continue;
+      prev = (prev_quant!=NULL) ? prev_quant[i] : 0;
+      c=0;
+      do {
+         int q2;
+         celt_glog offset;
+         q2 = ec_dec_bits(dec, extra);
+#ifdef FIXED_POINT
+         offset = SUB32(VSHR32(2*q2+1, extra-DB_SHIFT+1), GCONST(.5f));
+         offset = SHR32(offset, prev);
+#else
+         offset = (q2+.5f)*(1<<(14-extra))*(1.f/16384) - .5f;
+         offset *= (1<<(14-prev))*(1.f/16384);
+#endif
+         oldEBands[i+c*m->nbEBands] += offset;
+      } while (++c < C);
+   }
+}
+
+void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec, int C)
+{
+   int i, prio, c;
+
+   /* Use up the remaining bits */
+   for (prio=0;prio<2;prio++)
+   {
+      for (i=start;i<end && bits_left>=C ;i++)
+      {
+         if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
+            continue;
+         c=0;
+         do {
+            int q2;
+            celt_glog offset;
+            q2 = ec_dec_bits(dec, 1);
+#ifdef FIXED_POINT
+            offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
+#else
+            offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+            if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset;
+            bits_left--;
+         } while (++c < C);
+      }
+   }
+}
+
+void amp2Log2(const CELTMode *m, int effEnd, int end,
+      celt_ener *bandE, celt_glog *bandLogE, int C)
+{
+   int c, i;
+   c=0;
+   do {
+      for (i=0;i<effEnd;i++)
+      {
+         bandLogE[i+c*m->nbEBands] =
+               celt_log2_db(bandE[i+c*m->nbEBands])
+               - SHL32((celt_glog)eMeans[i],DB_SHIFT-4);
+#ifdef FIXED_POINT
+         /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
+         bandLogE[i+c*m->nbEBands] += GCONST(2.f);
+#endif
+      }
+      for (i=effEnd;i<end;i++)
+         bandLogE[c*m->nbEBands+i] = -GCONST(14.f);
+   } while (++c < C);
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/quant_bands.h
new file mode 100644 (file)
index 0000000..6677fca
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef QUANT_BANDS
+#define QUANT_BANDS
+
+#include "arch.h"
+#include "modes.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "mathops.h"
+
+#ifdef FIXED_POINT
+extern const signed char eMeans[25];
+#else
+extern const opus_val16 eMeans[25];
+#endif
+
+void amp2Log2(const CELTMode *m, int effEnd, int end,
+      celt_ener *bandE, celt_glog *bandLogE, int C);
+
+void log2Amp(const CELTMode *m, int start, int end,
+      celt_ener *eBands, const celt_glog *oldEBands, int C);
+
+void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
+      const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
+      celt_glog *error, ec_enc *enc, int C, int LM,
+      int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
+      int two_pass, int loss_rate, int lfe);
+
+void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *extra_quant, ec_enc *enc, int C);
+
+void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C);
+
+void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM);
+
+void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *extra_quant, ec_dec *dec, int C);
+
+void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C);
+
+#endif /* QUANT_BANDS */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.c
new file mode 100644 (file)
index 0000000..9eed2e1
--- /dev/null
@@ -0,0 +1,876 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "modes.h"
+#include "cwrs.h"
+#include "arch.h"
+#include "os_support.h"
+
+#include "entcode.h"
+#include "rate.h"
+#include "quant_bands.h"
+
+static const unsigned char LOG2_FRAC_TABLE[24]={
+   0,
+   8,13,
+  16,19,21,23,
+  24,26,27,28,29,30,31,32,
+  32,33,34,34,35,36,36,37,37
+};
+
+#if defined(CUSTOM_MODES)
+
+/*Determines if V(N,K) fits in a 32-bit unsigned integer.
+  N and K are themselves limited to 15 bits.*/
+static int fits_in32(int _n, int _k)
+{
+   static const opus_int16 maxN[15] = {
+      32767, 32767, 32767, 1476, 283, 109,  60,  40,
+       29,  24,  20,  18,  16,  14,  13};
+   static const opus_int16 maxK[15] = {
+      32767, 32767, 32767, 32767, 1172, 238,  95,  53,
+       36,  27,  22,  18,  16,  15,  13};
+   if (_n>=14)
+   {
+      if (_k>=14)
+         return 0;
+      else
+         return _n <= maxN[_k];
+   } else {
+      return _k <= maxK[_n];
+   }
+}
+
+void compute_pulse_cache(CELTMode *m, int LM)
+{
+   int C;
+   int i;
+   int j;
+   int curr=0;
+   int nbEntries=0;
+   int entryN[100], entryK[100], entryI[100];
+   const opus_int16 *eBands = m->eBands;
+   PulseCache *cache = &m->cache;
+   opus_int16 *cindex;
+   unsigned char *bits;
+   unsigned char *cap;
+
+   cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
+   cache->index = cindex;
+
+   /* Scan for all unique band sizes */
+   for (i=0;i<=LM+1;i++)
+   {
+      for (j=0;j<m->nbEBands;j++)
+      {
+         int k;
+         int N = (eBands[j+1]-eBands[j])<<i>>1;
+         cindex[i*m->nbEBands+j] = -1;
+         /* Find other bands that have the same size */
+         for (k=0;k<=i;k++)
+         {
+            int n;
+            for (n=0;n<m->nbEBands && (k!=i || n<j);n++)
+            {
+               if (N == (eBands[n+1]-eBands[n])<<k>>1)
+               {
+                  cindex[i*m->nbEBands+j] = cindex[k*m->nbEBands+n];
+                  break;
+               }
+            }
+         }
+         if (cache->index[i*m->nbEBands+j] == -1 && N!=0)
+         {
+            int K;
+            entryN[nbEntries] = N;
+            K = 0;
+            while (fits_in32(N,get_pulses(K+1)) && K<MAX_PSEUDO)
+               K++;
+            entryK[nbEntries] = K;
+            cindex[i*m->nbEBands+j] = curr;
+            entryI[nbEntries] = curr;
+
+            curr += K+1;
+            nbEntries++;
+         }
+      }
+   }
+   bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr);
+   cache->bits = bits;
+   cache->size = curr;
+   /* Compute the cache for all unique sizes */
+   for (i=0;i<nbEntries;i++)
+   {
+      unsigned char *ptr = bits+entryI[i];
+      opus_int16 tmp[CELT_MAX_PULSES+1];
+      get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
+      for (j=1;j<=entryK[i];j++)
+         ptr[j] = tmp[get_pulses(j)]-1;
+      ptr[0] = entryK[i];
+   }
+
+   /* Compute the maximum rate for each band at which we'll reliably use as
+       many bits as we ask for. */
+   cache->caps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
+   for (i=0;i<=LM;i++)
+   {
+      for (C=1;C<=2;C++)
+      {
+         for (j=0;j<m->nbEBands;j++)
+         {
+            int N0;
+            int max_bits;
+            N0 = m->eBands[j+1]-m->eBands[j];
+            /* N=1 bands only have a sign bit and fine bits. */
+            if (N0<<i == 1)
+               max_bits = C*(1+MAX_FINE_BITS)<<BITRES;
+            else
+            {
+               const unsigned char *pcache;
+               opus_int32           num;
+               opus_int32           den;
+               int                  LM0;
+               int                  N;
+               int                  offset;
+               int                  ndof;
+               int                  qb;
+               int                  k;
+               LM0 = 0;
+               /* Even-sized bands bigger than N=2 can be split one more time.
+                  As of commit 44203907 all bands >1 are even, including custom modes.*/
+               if (N0 > 2)
+               {
+                  N0>>=1;
+                  LM0--;
+               }
+               /* N0=1 bands can't be split down to N<2. */
+               else if (N0 <= 1)
+               {
+                  LM0=IMIN(i,1);
+                  N0<<=LM0;
+               }
+               /* Compute the cost for the lowest-level PVQ of a fully split
+                   band. */
+               pcache = bits + cindex[(LM0+1)*m->nbEBands+j];
+               max_bits = pcache[pcache[0]]+1;
+               /* Add in the cost of coding regular splits. */
+               N = N0;
+               for(k=0;k<i-LM0;k++){
+                  max_bits <<= 1;
+                  /* Offset the number of qtheta bits by log2(N)/2
+                      + QTHETA_OFFSET compared to their "fair share" of
+                      total/N */
+                  offset = ((m->logN[j]+(opus_int32)((opus_uint32)(LM0+k)<<BITRES))>>1)-QTHETA_OFFSET;
+                  /* The number of qtheta bits we'll allocate if the remainder
+                      is to be max_bits.
+                     The average measured cost for theta is 0.89701 times qb,
+                      approximated here as 459/512. */
+                  num=459*(opus_int32)((2*N-1)*offset+max_bits);
+                  den=((opus_int32)(2*N-1)<<9)-459;
+                  qb = IMIN((num+(den>>1))/den, 57);
+                  celt_assert(qb >= 0);
+                  max_bits += qb;
+                  N <<= 1;
+               }
+               /* Add in the cost of a stereo split, if necessary. */
+               if (C==2)
+               {
+                  max_bits <<= 1;
+                  offset = ((m->logN[j]+(i<<BITRES))>>1)-(N==2?QTHETA_OFFSET_TWOPHASE:QTHETA_OFFSET);
+                  ndof = 2*N-1-(N==2);
+                  /* The average measured cost for theta with the step PDF is
+                      0.95164 times qb, approximated here as 487/512. */
+                  num = (N==2?512:487)*(opus_int32)(max_bits+ndof*offset);
+                  den = ((opus_int32)ndof<<9)-(N==2?512:487);
+                  qb = IMIN((num+(den>>1))/den, (N==2?64:61));
+                  celt_assert(qb >= 0);
+                  max_bits += qb;
+               }
+               /* Add the fine bits we'll use. */
+               /* Compensate for the extra DoF in stereo */
+               ndof = C*N + ((C==2 && N>2) ? 1 : 0);
+               /* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET
+                   compared to their "fair share" of total/N */
+               offset = ((m->logN[j] + (i<<BITRES))>>1)-FINE_OFFSET;
+               /* N=2 is the only point that doesn't match the curve */
+               if (N==2)
+                  offset += 1<<BITRES>>2;
+               /* The number of fine bits we'll allocate if the remainder is
+                   to be max_bits. */
+               num = max_bits+ndof*offset;
+               den = (ndof-1)<<BITRES;
+               qb = IMIN((num+(den>>1))/den, MAX_FINE_BITS);
+               celt_assert(qb >= 0);
+               max_bits += C*qb<<BITRES;
+            }
+            max_bits = (4*max_bits/(C*((m->eBands[j+1]-m->eBands[j])<<i)))-64;
+            celt_assert(max_bits >= 0);
+            celt_assert(max_bits < 256);
+            *cap++ = (unsigned char)max_bits;
+         }
+      }
+   }
+}
+
+#endif /* CUSTOM_MODES */
+
+#define ALLOC_STEPS 6
+
+static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start,
+      const int *bits1, const int *bits2, const int *thresh, const int *cap, opus_int32 total, opus_int32 *_balance,
+      int skip_rsv, int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits,
+      int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
+{
+   opus_int32 psum;
+   int lo, hi;
+   int i, j;
+   int logM;
+   int stereo;
+   int codedBands=-1;
+   int alloc_floor;
+   opus_int32 left, percoeff;
+   int done;
+   opus_int32 balance;
+   SAVE_STACK;
+
+   alloc_floor = C<<BITRES;
+   stereo = C>1;
+
+   logM = LM<<BITRES;
+   lo = 0;
+   hi = 1<<ALLOC_STEPS;
+   for (i=0;i<ALLOC_STEPS;i++)
+   {
+      int mid = (lo+hi)>>1;
+      psum = 0;
+      done = 0;
+      for (j=end;j-->start;)
+      {
+         int tmp = bits1[j] + (mid*(opus_int32)bits2[j]>>ALLOC_STEPS);
+         if (tmp >= thresh[j] || done)
+         {
+            done = 1;
+            /* Don't allocate more than we can actually use */
+            psum += IMIN(tmp, cap[j]);
+         } else {
+            if (tmp >= alloc_floor)
+               psum += alloc_floor;
+         }
+      }
+      if (psum > total)
+         hi = mid;
+      else
+         lo = mid;
+   }
+   psum = 0;
+   /*printf ("interp bisection gave %d\n", lo);*/
+   done = 0;
+   for (j=end;j-->start;)
+   {
+      int tmp = bits1[j] + ((opus_int32)lo*bits2[j]>>ALLOC_STEPS);
+      if (tmp < thresh[j] && !done)
+      {
+         if (tmp >= alloc_floor)
+            tmp = alloc_floor;
+         else
+            tmp = 0;
+      } else
+         done = 1;
+      /* Don't allocate more than we can actually use */
+      tmp = IMIN(tmp, cap[j]);
+      bits[j] = tmp;
+      psum += tmp;
+   }
+
+   /* Decide which bands to skip, working backwards from the end. */
+   for (codedBands=end;;codedBands--)
+   {
+      int band_width;
+      int band_bits;
+      int rem;
+      j = codedBands-1;
+      /* Never skip the first band, nor a band that has been boosted by
+          dynalloc.
+         In the first case, we'd be coding a bit to signal we're going to waste
+          all the other bits.
+         In the second case, we'd be coding a bit to redistribute all the bits
+          we just signaled should be concentrated in this band. */
+      if (j<=skip_start)
+      {
+         /* Give the bit we reserved to end skipping back. */
+         total += skip_rsv;
+         break;
+      }
+      /*Figure out how many left-over bits we would be adding to this band.
+        This can include bits we've stolen back from higher, skipped bands.*/
+      left = total-psum;
+      percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
+      left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
+      rem = IMAX(left-(m->eBands[j]-m->eBands[start]),0);
+      band_width = m->eBands[codedBands]-m->eBands[j];
+      band_bits = (int)(bits[j] + percoeff*band_width + rem);
+      /*Only code a skip decision if we're above the threshold for this band.
+        Otherwise it is force-skipped.
+        This ensures that we have enough bits to code the skip flag.*/
+      if (band_bits >= IMAX(thresh[j], alloc_floor+(1<<BITRES)))
+      {
+         if (encode)
+         {
+            /*This if() block is the only part of the allocation function that
+               is not a mandatory part of the bitstream: any bands we choose to
+               skip here must be explicitly signaled.*/
+            int depth_threshold;
+            /*We choose a threshold with some hysteresis to keep bands from
+               fluctuating in and out, but we try not to fold below a certain point. */
+            if (codedBands > 17)
+               depth_threshold = j<prev ? 7 : 9;
+            else
+               depth_threshold = 0;
+#ifdef FUZZING
+            (void)signalBandwidth;
+            (void)depth_threshold;
+            if ((rand()&0x1) == 0)
+#else
+            if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
+#endif
+            {
+               ec_enc_bit_logp(ec, 1, 1);
+               break;
+            }
+            ec_enc_bit_logp(ec, 0, 1);
+         } else if (ec_dec_bit_logp(ec, 1)) {
+            break;
+         }
+         /*We used a bit to skip this band.*/
+         psum += 1<<BITRES;
+         band_bits -= 1<<BITRES;
+      }
+      /*Reclaim the bits originally allocated to this band.*/
+      psum -= bits[j]+intensity_rsv;
+      if (intensity_rsv > 0)
+         intensity_rsv = LOG2_FRAC_TABLE[j-start];
+      psum += intensity_rsv;
+      if (band_bits >= alloc_floor)
+      {
+         /*If we have enough for a fine energy bit per channel, use it.*/
+         psum += alloc_floor;
+         bits[j] = alloc_floor;
+      } else {
+         /*Otherwise this band gets nothing at all.*/
+         bits[j] = 0;
+      }
+   }
+
+   celt_assert(codedBands > start);
+   /* Code the intensity and dual stereo parameters. */
+   if (intensity_rsv > 0)
+   {
+      if (encode)
+      {
+         *intensity = IMIN(*intensity, codedBands);
+         ec_enc_uint(ec, *intensity-start, codedBands+1-start);
+      }
+      else
+         *intensity = start+ec_dec_uint(ec, codedBands+1-start);
+   }
+   else
+      *intensity = 0;
+   if (*intensity <= start)
+   {
+      total += dual_stereo_rsv;
+      dual_stereo_rsv = 0;
+   }
+   if (dual_stereo_rsv > 0)
+   {
+      if (encode)
+         ec_enc_bit_logp(ec, *dual_stereo, 1);
+      else
+         *dual_stereo = ec_dec_bit_logp(ec, 1);
+   }
+   else
+      *dual_stereo = 0;
+
+   /* Allocate the remaining bits */
+   left = total-psum;
+   percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
+   left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
+   for (j=start;j<codedBands;j++)
+      bits[j] += ((int)percoeff*(m->eBands[j+1]-m->eBands[j]));
+   for (j=start;j<codedBands;j++)
+   {
+      int tmp = (int)IMIN(left, m->eBands[j+1]-m->eBands[j]);
+      bits[j] += tmp;
+      left -= tmp;
+   }
+   /*for (j=0;j<end;j++)printf("%d ", bits[j]);printf("\n");*/
+
+   balance = 0;
+   for (j=start;j<codedBands;j++)
+   {
+      int N0, N, den;
+      int offset;
+      int NClogN;
+      opus_int32 excess, bit;
+
+      celt_assert(bits[j] >= 0);
+      N0 = m->eBands[j+1]-m->eBands[j];
+      N=N0<<LM;
+      bit = (opus_int32)bits[j]+balance;
+
+      if (N>1)
+      {
+         excess = MAX32(bit-cap[j],0);
+         bits[j] = bit-excess;
+
+         /* Compensate for the extra DoF in stereo */
+         den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0));
+
+         NClogN = den*(m->logN[j] + logM);
+
+         /* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET
+            compared to their "fair share" of total/N */
+         offset = (NClogN>>1)-den*FINE_OFFSET;
+
+         /* N=2 is the only point that doesn't match the curve */
+         if (N==2)
+            offset += den<<BITRES>>2;
+
+         /* Changing the offset for allocating the second and third
+             fine energy bit */
+         if (bits[j] + offset < den*2<<BITRES)
+            offset += NClogN>>2;
+         else if (bits[j] + offset < den*3<<BITRES)
+            offset += NClogN>>3;
+
+         /* Divide with rounding */
+         ebits[j] = IMAX(0, (bits[j] + offset + (den<<(BITRES-1))));
+         ebits[j] = celt_udiv(ebits[j], den)>>BITRES;
+
+         /* Make sure not to bust */
+         if (C*ebits[j] > (bits[j]>>BITRES))
+            ebits[j] = bits[j] >> stereo >> BITRES;
+
+         /* More than that is useless because that's about as far as PVQ can go */
+         ebits[j] = IMIN(ebits[j], MAX_FINE_BITS);
+
+         /* If we rounded down or capped this band, make it a candidate for the
+             final fine energy pass */
+         fine_priority[j] = ebits[j]*(den<<BITRES) >= bits[j]+offset;
+
+         /* Remove the allocated fine bits; the rest are assigned to PVQ */
+         bits[j] -= C*ebits[j]<<BITRES;
+
+      } else {
+         /* For N=1, all bits go to fine energy except for a single sign bit */
+         excess = MAX32(0,bit-(C<<BITRES));
+         bits[j] = bit-excess;
+         ebits[j] = 0;
+         fine_priority[j] = 1;
+      }
+
+      /* Fine energy can't take advantage of the re-balancing in
+          quant_all_bands().
+         Instead, do the re-balancing here.*/
+      if(excess > 0)
+      {
+         int extra_fine;
+         int extra_bits;
+         extra_fine = IMIN(excess>>(stereo+BITRES),MAX_FINE_BITS-ebits[j]);
+         ebits[j] += extra_fine;
+         extra_bits = extra_fine*C<<BITRES;
+         fine_priority[j] = extra_bits >= excess-balance;
+         excess -= extra_bits;
+      }
+      balance = excess;
+
+      celt_assert(bits[j] >= 0);
+      celt_assert(ebits[j] >= 0);
+   }
+   /* Save any remaining bits over the cap for the rebalancing in
+       quant_all_bands(). */
+   *_balance = balance;
+
+   /* The skipped bands use all their bits for fine energy. */
+   for (;j<end;j++)
+   {
+      ebits[j] = bits[j] >> stereo >> BITRES;
+      celt_assert(C*ebits[j]<<BITRES == bits[j]);
+      bits[j] = 0;
+      fine_priority[j] = ebits[j]<1;
+   }
+   RESTORE_STACK;
+   return codedBands;
+}
+
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+      opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
+{
+   int lo, hi, len, j;
+   int codedBands;
+   int skip_start;
+   int skip_rsv;
+   int intensity_rsv;
+   int dual_stereo_rsv;
+   VARDECL(int, bits1);
+   VARDECL(int, bits2);
+   VARDECL(int, thresh);
+   VARDECL(int, trim_offset);
+   SAVE_STACK;
+
+   total = IMAX(total, 0);
+   len = m->nbEBands;
+   skip_start = start;
+   /* Reserve a bit to signal the end of manually skipped bands. */
+   skip_rsv = total >= 1<<BITRES ? 1<<BITRES : 0;
+   total -= skip_rsv;
+   /* Reserve bits for the intensity and dual stereo parameters. */
+   intensity_rsv = dual_stereo_rsv = 0;
+   if (C==2)
+   {
+      intensity_rsv = LOG2_FRAC_TABLE[end-start];
+      if (intensity_rsv>total)
+         intensity_rsv = 0;
+      else
+      {
+         total -= intensity_rsv;
+         dual_stereo_rsv = total>=1<<BITRES ? 1<<BITRES : 0;
+         total -= dual_stereo_rsv;
+      }
+   }
+   ALLOC(bits1, len, int);
+   ALLOC(bits2, len, int);
+   ALLOC(thresh, len, int);
+   ALLOC(trim_offset, len, int);
+
+   for (j=start;j<end;j++)
+   {
+      /* Below this threshold, we're sure not to allocate any PVQ bits */
+      thresh[j] = IMAX((C)<<BITRES, (3*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>4);
+      /* Tilt of the allocation curve */
+      trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(end-j-1)
+            *(1<<(LM+BITRES))>>6;
+      /* Giving less resolution to single-coefficient bands because they get
+         more benefit from having one coarse value per coefficient*/
+      if ((m->eBands[j+1]-m->eBands[j])<<LM==1)
+         trim_offset[j] -= C<<BITRES;
+   }
+   lo = 1;
+   hi = m->nbAllocVectors - 1;
+   do
+   {
+      int done = 0;
+      int psum = 0;
+      int mid = (lo+hi) >> 1;
+      for (j=end;j-->start;)
+      {
+         int bitsj;
+         int N = m->eBands[j+1]-m->eBands[j];
+         bitsj = C*N*m->allocVectors[mid*len+j]<<LM>>2;
+         if (bitsj > 0)
+            bitsj = IMAX(0, bitsj + trim_offset[j]);
+         bitsj += offsets[j];
+         if (bitsj >= thresh[j] || done)
+         {
+            done = 1;
+            /* Don't allocate more than we can actually use */
+            psum += IMIN(bitsj, cap[j]);
+         } else {
+            if (bitsj >= C<<BITRES)
+               psum += C<<BITRES;
+         }
+      }
+      if (psum > total)
+         hi = mid - 1;
+      else
+         lo = mid + 1;
+      /*printf ("lo = %d, hi = %d\n", lo, hi);*/
+   }
+   while (lo <= hi);
+   hi = lo--;
+   /*printf ("interp between %d and %d\n", lo, hi);*/
+   for (j=start;j<end;j++)
+   {
+      int bits1j, bits2j;
+      int N = m->eBands[j+1]-m->eBands[j];
+      bits1j = C*N*m->allocVectors[lo*len+j]<<LM>>2;
+      bits2j = hi>=m->nbAllocVectors ?
+            cap[j] : C*N*m->allocVectors[hi*len+j]<<LM>>2;
+      if (bits1j > 0)
+         bits1j = IMAX(0, bits1j + trim_offset[j]);
+      if (bits2j > 0)
+         bits2j = IMAX(0, bits2j + trim_offset[j]);
+      if (lo > 0)
+         bits1j += offsets[j];
+      bits2j += offsets[j];
+      if (offsets[j]>0)
+         skip_start = j;
+      bits2j = IMAX(0,bits2j-bits1j);
+      bits1[j] = bits1j;
+      bits2[j] = bits2j;
+   }
+   codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
+         total, balance, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv,
+         pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth);
+   RESTORE_STACK;
+   return codedBands;
+}
+#ifdef ENABLE_QEXT
+
+static const unsigned char last_zero[3] = {64, 50, 0};
+static const unsigned char last_cap[3] = {110, 60, 0};
+static const unsigned char last_other[4] = {120, 112, 70, 0};
+
+static void ec_enc_depth(ec_enc *enc, opus_int32 depth, opus_int32 cap, opus_int32 *last) {
+   int sym = 3;
+   if (depth==*last) sym = 2;
+   if (depth==cap) sym = 1;
+   if (depth==0) sym = 0;
+   if (*last == 0) {
+      ec_enc_icdf(enc, IMIN(sym, 2), last_zero, 7);
+   } else if (*last == cap) {
+      ec_enc_icdf(enc, IMIN(sym, 2), last_cap, 7);
+   } else {
+      ec_enc_icdf(enc, sym, last_other, 7);
+   }
+   /* We accept some redundancy if depth==last (for last different from 0 and cap). */
+   if (sym == 3) ec_enc_uint(enc, depth-1, cap);
+   *last = depth;
+}
+
+static int ec_dec_depth(ec_dec *dec, opus_int32 cap, opus_int32 *last) {
+   int depth, sym;
+   if (*last == 0) {
+      sym = ec_dec_icdf(dec, last_zero, 7);
+      if (sym==2) sym=3;
+   } else if (*last == cap) {
+      sym = ec_dec_icdf(dec, last_cap, 7);
+      if (sym==2) sym=3;
+   } else {
+      sym = ec_dec_icdf(dec, last_other, 7);
+   }
+   if (sym==0) depth=0;
+   else if (sym==1) depth=cap;
+   else if (sym==2) depth=*last;
+   else depth = 1 + ec_dec_uint(dec, cap);
+   *last = depth;
+   return depth;
+}
+
+#define MSWAP16(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0)
+static opus_val16 median_of_5_val16(const opus_val16 *x)
+{
+   opus_val16 t0, t1, t2, t3, t4;
+   t2 = x[2];
+   if (x[0] > x[1])
+   {
+      t0 = x[1];
+      t1 = x[0];
+   } else {
+      t0 = x[0];
+      t1 = x[1];
+   }
+   if (x[3] > x[4])
+   {
+      t3 = x[4];
+      t4 = x[3];
+   } else {
+      t3 = x[3];
+      t4 = x[4];
+   }
+   if (t0 > t3)
+   {
+      MSWAP16(t0, t3);
+      MSWAP16(t1, t4);
+   }
+   if (t2 > t1)
+   {
+      if (t1 < t3)
+         return MIN16(t2, t3);
+      else
+         return MIN16(t4, t1);
+   } else {
+      if (t2 < t3)
+         return MIN16(t1, t3);
+      else
+         return MIN16(t2, t4);
+   }
+}
+
+void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE,
+      opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness)
+{
+   int i;
+   opus_int32 last=0;
+   opus_val32 sum;
+   opus_val32 fill;
+   int iter;
+   int tot_bands;
+   int tot_samples;
+   VARDECL(int, depth);
+   VARDECL(opus_int32, cap);
+#ifdef FUZZING
+   float depth_std;
+#endif
+   SAVE_STACK;
+#ifdef FUZZING
+   depth_std = -10.f*log(1e-8+(float)rand()/(float)RAND_MAX);
+   depth_std = FMAX(0, FMIN(48, depth_std));
+#endif
+   if (qext_mode != NULL) {
+      celt_assert(end==m->nbEBands);
+      tot_bands = end + qext_end;
+      tot_samples = qext_mode->eBands[qext_end]*C<<LM;
+   } else {
+      tot_bands = end;
+      tot_samples = (m->eBands[end]-m->eBands[start])*C<<LM;
+   }
+   ALLOC(cap, tot_bands, opus_int32);
+   for (i=start;i<end;i++) cap[i] = 12;
+   if (qext_mode != NULL) {
+      for (i=0;i<qext_end;i++) cap[end+i] = 14;
+   }
+   if (total <= 0) {
+      for (i=start;i<m->nbEBands+qext_end;i++) {
+         extra_pulses[i] = extra_equant[i] = 0;
+      }
+      RESTORE_STACK;
+      return;
+   }
+   ALLOC(depth, tot_bands, int);
+   if (encode) {
+      VARDECL(opus_val16, flatE);
+      VARDECL(int, Ncoef);
+      VARDECL(opus_val16, min);
+      VARDECL(opus_val16, follower);
+
+      ALLOC(flatE, tot_bands, opus_val16);
+      ALLOC(min, tot_bands, opus_val16);
+      ALLOC(Ncoef, tot_bands, int);
+      for (i=start;i<end;i++) {
+         Ncoef[i] = (m->eBands[i+1]-m->eBands[i])*C<<LM;
+      }
+      /* Remove the effect of band width, eMeans and pre-emphasis to compute the real (flat) spectrum. */
+      for (i=start;i<end;i++) {
+         flatE[i] = PSHR32(bandLogE[i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10);
+         min[i] = 0;
+      }
+      if (C==2) {
+         for (i=start;i<end;i++) {
+            flatE[i] = MAXG(flatE[i], PSHR32(bandLogE[m->nbEBands+i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10));
+         }
+      }
+      flatE[end-1] += QCONST16(2.f, 10);
+      if (qext_mode != NULL) {
+         opus_val16 min_depth = 0;
+         /* If we have enough bits, give at least 1 bit of depth to all higher bands. */
+         if (total >= 3*C*(qext_mode->eBands[qext_end]-qext_mode->eBands[start])<<LM<<BITRES && (toneishness < QCONST32(.98f, 29) || tone_freq > 1.33f))
+            min_depth = QCONST16(1.f, 10);
+         for (i=0;i<qext_end;i++) {
+            Ncoef[end+i] = (qext_mode->eBands[i+1]-qext_mode->eBands[i])*C<<LM;
+            min[end+i] = min_depth;
+         }
+         for (i=0;i<qext_end;i++) {
+            flatE[end+i] = PSHR32(qext_bandLogE[i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10);
+         }
+         if (C==2) {
+            for (i=0;i<qext_end;i++) {
+               flatE[end+i] = MAXG(flatE[end+i], PSHR32(qext_bandLogE[NB_QEXT_BANDS+i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10));
+            }
+         }
+      }
+      ALLOC(follower, tot_bands, opus_val16);
+      for (i=start+2;i<tot_bands-2;i++) {
+         follower[i] = median_of_5_val16(&flatE[i-2]);
+      }
+      follower[start] = follower[start+1] = follower[start+2];
+      follower[tot_bands-1] = follower[tot_bands-2] = follower[tot_bands-3];
+      for (i=start+1;i<tot_bands;i++) {
+         follower[i] = MAX16(follower[i], follower[i-1]-QCONST16(1.f, 10));
+      }
+      for (i=tot_bands-2;i>=start;i--) {
+         follower[i] = MAX16(follower[i], follower[i+1]-QCONST16(1.f, 10));
+      }
+      for (i=start;i<tot_bands;i++) flatE[i] -= MULT16_16_Q15(Q15ONE-PSHR32(toneishness, 14), follower[i]);
+      if (qext_mode != NULL) {
+         for (i=0;i<qext_end;i++) flatE[end+i] = flatE[end+i] + QCONST16(3.f, 10) + QCONST16(.2f, 10)*i;
+      }
+      /* Approximate fill level assuming all bands contribute fully. */
+      sum = 0;
+      for (i=start;i<tot_bands;i++) {
+         sum += MULT16_16(Ncoef[i], flatE[i]);
+      }
+      total >>= BITRES;
+      fill = (SHL32(total, 10) + sum)/tot_samples;
+      /* Iteratively refine the fill level considering the depth min and cap. */
+      for (iter=0;iter<10;iter++) {
+         sum = 0;
+         for (i=start;i<tot_bands;i++)
+            sum += Ncoef[i] * MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill));
+         fill -= (SHL32(total, 10) - sum)/tot_samples;
+      }
+      for (i=start;i<tot_bands;i++) {
+#ifdef FIXED_POINT
+         depth[i] = PSHR32(MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)), 10-2);
+#else
+         depth[i] = (int)floor(.5+4*MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)));
+#endif
+#ifdef FUZZING
+         depth[i] = (int)-depth_std*log(1e-8+(float)rand()/(float)RAND_MAX);
+         depth[i] = IMAX(0, IMIN(cap[i]<<2, depth[i]));
+#endif
+         if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES)
+            ec_enc_depth(ec, depth[i], 4*cap[i], &last);
+         else
+            depth[i] = 0;
+      }
+   } else {
+      for (i=start;i<tot_bands;i++) {
+         if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES)
+            depth[i] = ec_dec_depth(ec, 4*cap[i], &last);
+         else
+            depth[i] = 0;
+      }
+   }
+   for (i=start;i<end;i++) {
+      extra_equant[i] = (depth[i]+3)>>2;
+      extra_pulses[i] = ((((m->eBands[i+1]-m->eBands[i])<<LM)-1)*C * depth[i] * (1<<BITRES) + 2)>>2;
+   }
+   if (qext_mode) {
+      for (i=0;i<qext_end;i++) {
+         extra_equant[end+i] = (depth[end+i]+3)>>2;
+         extra_pulses[end+i] = ((((qext_mode->eBands[i+1]-qext_mode->eBands[i])<<LM)-1)*C * depth[end+i] * (1<<BITRES) + 2)>>2;
+      }
+   }
+   RESTORE_STACK;
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/rate.h
new file mode 100644 (file)
index 0000000..659c80f
--- /dev/null
@@ -0,0 +1,104 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef RATE_H
+#define RATE_H
+
+#define MAX_PSEUDO 40
+#define LOG_MAX_PSEUDO 6
+
+#define CELT_MAX_PULSES 128
+
+#define MAX_FINE_BITS 8
+
+#define FINE_OFFSET 21
+#define QTHETA_OFFSET 4
+#define QTHETA_OFFSET_TWOPHASE 16
+
+#include "cwrs.h"
+#include "modes.h"
+
+void compute_pulse_cache(CELTMode *m, int LM);
+
+static OPUS_INLINE int get_pulses(int i)
+{
+   return i<8 ? i : (8 + (i&7)) << ((i>>3)-1);
+}
+
+static OPUS_INLINE int bits2pulses(const CELTMode *m, int band, int LM, int bits)
+{
+   int i;
+   int lo, hi;
+   const unsigned char *cache;
+
+   LM++;
+   cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
+
+   lo = 0;
+   hi = cache[0];
+   bits--;
+   for (i=0;i<LOG_MAX_PSEUDO;i++)
+   {
+      int mid = (lo+hi+1)>>1;
+      /* OPT: Make sure this is implemented with a conditional move */
+      if ((int)cache[mid] >= bits)
+         hi = mid;
+      else
+         lo = mid;
+   }
+   if (bits- (lo == 0 ? -1 : (int)cache[lo]) <= (int)cache[hi]-bits)
+      return lo;
+   else
+      return hi;
+}
+
+static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int pulses)
+{
+   const unsigned char *cache;
+
+   LM++;
+   cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
+   return pulses == 0 ? 0 : cache[pulses]+1;
+}
+
+/** Compute the pulse allocation, i.e. how many pulses will go in each
+  * band.
+ @param m mode
+ @param offsets Requested increase or decrease in the number of bits for
+                each band
+ @param total Number of bands
+ @param pulses Number of pulses per band (returned)
+ @return Total number of bits allocated
+*/
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+      opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth);
+
+void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE,
+      opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/stack_alloc.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/stack_alloc.h
new file mode 100644 (file)
index 0000000..04b14ff
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright (C) 2002-2003 Jean-Marc Valin
+   Copyright (C) 2007-2009 Xiph.Org Foundation */
+/**
+   @file stack_alloc.h
+   @brief Temporary memory allocation on stack
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef STACK_ALLOC_H
+#define STACK_ALLOC_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
+#error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
+#endif
+
+#ifdef USE_ALLOCA
+# ifdef _WIN32
+#  include <malloc.h>
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   include <stdlib.h>
+#  endif
+# endif
+#endif
+
+/**
+ * @def ALIGN(stack, size)
+ *
+ * Aligns the stack to a 'size' boundary
+ *
+ * @param stack Stack
+ * @param size  New size boundary
+ */
+
+/**
+ * @def PUSH(stack, size, type)
+ *
+ * Allocates 'size' elements of type 'type' on the stack
+ *
+ * @param stack Stack
+ * @param size  Number of elements
+ * @param type  Type of element
+ */
+
+/**
+ * @def VARDECL(var)
+ *
+ * Declare variable on stack
+ *
+ * @param var Variable to declare
+ */
+
+/**
+ * @def ALLOC(var, size, type)
+ *
+ * Allocate 'size' elements of 'type' on stack
+ *
+ * @param var  Name of variable to allocate
+ * @param size Number of elements
+ * @param type Type of element
+ */
+
+#if defined(VAR_ARRAYS)
+
+#define VARDECL(type, var)
+#define ALLOC(var, size, type) type var[size]
+#define SAVE_STACK
+#define RESTORE_STACK
+#define ALLOC_STACK
+/* C99 does not allow VLAs of size zero */
+#define ALLOC_NONE 1
+
+#elif defined(USE_ALLOCA)
+
+#define VARDECL(type, var) type *var
+
+# ifdef _WIN32
+#  define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
+# else
+#  define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
+# endif
+
+#define SAVE_STACK
+#define RESTORE_STACK
+#define ALLOC_STACK
+#define ALLOC_NONE 0
+
+#else
+
+#ifdef CELT_C
+char *scratch_ptr=0;
+char *global_stack=0;
+#else
+extern char *global_stack;
+extern char *scratch_ptr;
+#endif /* CELT_C */
+
+#if __STDC_VERSION__ >= 201112L
+#  include <stdalign.h>
+#  define ALIGNOF(T) alignof(T)
+#elif defined(__GNUC__) || defined(__clang__)
+#  define ALIGNOF(T) __alignof__(T)
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+template <typename T>
+struct alignment_helper {
+    char c;
+    T member;
+};
+# define ALIGNOF(T) (offsetof(alignment_helper<T>, member))
+# else
+# define ALIGNOF(T) (offsetof(struct { char c; T member; }, member))
+# endif
+#endif
+
+#ifdef ENABLE_VALGRIND
+
+#include <valgrind/memcheck.h>
+
+#ifdef CELT_C
+char *global_stack_top=0;
+#else
+extern char *global_stack_top;
+#endif /* CELT_C */
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+#define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),ALIGNOF(type)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char))))
+#define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
+#define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=(char*)opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack;
+
+#else
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+#ifdef ENABLE_HARDENING
+#include "arch.h"
+#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(void)(((int)((size)*(sizeof(type)/(sizeof(char)))) <= (scratch_ptr)+GLOBAL_STACK_SIZE-(stack))?0:CELT_FATAL("pseudostack overflow")),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char)))))
+#else
+#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char)))))
+#endif
+
+#if 0 /* Set this to 1 to instrument pseudostack usage */
+#define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack)
+#else
+#define RESTORE_STACK (global_stack = _saved_stack)
+#endif
+#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? (scratch_ptr=(char*)opus_alloc_scratch(GLOBAL_STACK_SIZE)) : global_stack); _saved_stack = global_stack;
+
+#endif /* ENABLE_VALGRIND */
+
+#include "os_support.h"
+#define VARDECL(type, var) type *var
+#define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
+#define SAVE_STACK char *_saved_stack = global_stack;
+#define ALLOC_NONE 0
+
+#endif /* VAR_ARRAYS */
+
+
+#ifdef ENABLE_VALGRIND
+
+#include <valgrind/memcheck.h>
+#define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
+#define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
+#define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
+#define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
+#define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0)
+#define OPUS_FPRINTF fprintf
+
+#else
+
+static OPUS_INLINE int _opus_false(void) {return 0;}
+#define OPUS_CHECK_ARRAY(ptr, len) _opus_false()
+#define OPUS_CHECK_VALUE(value) _opus_false()
+#define OPUS_PRINT_INT(value) do{}while(0)
+#define OPUS_FPRINTF (void)
+
+#endif
+
+
+#endif /* STACK_ALLOC_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed.h
new file mode 100644 (file)
index 0000000..5bac867
--- /dev/null
@@ -0,0 +1,4446 @@
+/* The contents of this file was automatically generated by dump_modes.c
+   with arguments: 48000 960 96000 1920
+   It contains static definitions for some pre-defined modes. */
+#include "modes.h"
+#include "rate.h"
+
+#ifdef HAVE_ARM_NE10
+#define OVERRIDE_FFT 1
+#include "static_modes_fixed_arm_ne10.h"
+#endif
+
+#ifndef DEF_WINDOW120
+#define DEF_WINDOW120
+static const celt_coef window120[120] = {
+#ifdef ENABLE_QEXT
+144497, 1300330, 3611201, 7075520, 11690888,
+17454086, 24361057, 32406886, 41585775, 51891010,
+63314937, 75848919, 89483305, 104207389, 120009370,
+136876310, 154794092, 173747379, 193719571, 214692768,
+236647730, 259563841, 283419077, 308189974, 333851611,
+360377579, 387739975, 415909390, 444854905, 474544098,
+504943052, 536016380, 567727246, 600037405, 632907246,
+666295842, 700161014, 734459402, 769146541, 804176950,
+839504226, 875081152, 910859802, 946791664, 982827767,
+1018918807, 1055015290, 1091067670, 1127026498, 1162842573,
+1198467087, 1233851789, 1268949131, 1303712428, 1338096006,
+1372055358, 1405547288, 1438530058, 1470963524, 1502809271,
+1534030739, 1564593342, 1594464577, 1623614128, 1652013956,
+1679638382, 1706464158, 1732470524, 1757639263, 1781954729,
+1805403879, 1827976282, 1849664120, 1870462177, 1890367816,
+1909380946, 1927503971, 1944741741, 1961101475, 1976592692,
+1991227121, 2005018607, 2017983004, 2030138067, 2041503335,
+2052100006, 2061950806, 2071079861, 2079512553, 2087275384,
+2094395835, 2100902218, 2106823532, 2112189321, 2117029527,
+2121374347, 2125254092, 2128699049, 2131739343, 2134404804,
+2136724838, 2138728301, 2140443380, 2141897478, 2143117097,
+2144127740, 2144953807, 2145618502, 2146143741, 2146550077,
+2146856618, 2147080958, 2147239113, 2147345467, 2147412716,
+2147451825, 2147471991, 2147480611, 2147483254, 2147483643,
+#else
+2, 20, 55, 108, 178,
+266, 372, 494, 635, 792,
+966, 1157, 1365, 1590, 1831,
+2089, 2362, 2651, 2956, 3276,
+3611, 3961, 4325, 4703, 5094,
+5499, 5916, 6346, 6788, 7241,
+7705, 8179, 8663, 9156, 9657,
+10167, 10684, 11207, 11736, 12271,
+12810, 13353, 13899, 14447, 14997,
+15547, 16098, 16648, 17197, 17744,
+18287, 18827, 19363, 19893, 20418,
+20936, 21447, 21950, 22445, 22931,
+23407, 23874, 24330, 24774, 25208,
+25629, 26039, 26435, 26819, 27190,
+27548, 27893, 28224, 28541, 28845,
+29135, 29411, 29674, 29924, 30160,
+30384, 30594, 30792, 30977, 31151,
+31313, 31463, 31602, 31731, 31849,
+31958, 32057, 32148, 32229, 32303,
+32370, 32429, 32481, 32528, 32568,
+32604, 32634, 32661, 32683, 32701,
+32717, 32729, 32740, 32748, 32754,
+32758, 32762, 32764, 32766, 32767,
+32767, 32767, 32767, 32767, 32767,
+#endif
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES48000_960
+#define FFT_TWIDDLES48000_960
+static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
+#ifdef ENABLE_QEXT
+{2147483647, 0}, {2147299668, -28109692},
+{2146747759, -56214568}, {2145828016, -84309812},
+{2144540596, -112390610}, {2142885721, -140452151},
+{2140863673, -168489625}, {2138474799, -196498230},
+{2135719508, -224473166}, {2132598273, -252409639},
+{2129111628, -280302863}, {2125260170, -308148059},
+{2121044561, -335940456}, {2116465521, -363675290},
+{2111523836, -391347811}, {2106220352, -418953276},
+{2100555978, -446486956}, {2094531684, -473944133},
+{2088148504, -501320102}, {2081407530, -528610172},
+{2074309917, -555809667}, {2066856882, -582913927},
+{2059049702, -609918309}, {2050889714, -636818183},
+{2042378317, -663608942}, {2033516969, -690285996},
+{2024307188, -716844772}, {2014750553, -743280720},
+{2004848700, -769589312}, {1994603327, -795766038},
+{1984016189, -821806413}, {1973089100, -847705977},
+{1961823932, -873460290}, {1950222616, -899064940},
+{1938287139, -924515541}, {1926019547, -949807730},
+{1913421941, -974937175}, {1900496480, -999899569},
+{1887245379, -1024690635}, {1873670908, -1049306126},
+{1859775393, -1073741824}, {1845561216, -1097993542},
+{1831030811, -1122057124}, {1816186668, -1145928447},
+{1801031331, -1169603422}, {1785567396, -1193077991},
+{1769797514, -1216348132}, {1753724386, -1239409858},
+{1737350766, -1262259218}, {1720679461, -1284892296},
+{1703713325, -1307305214}, {1686455268, -1329494133},
+{1668908244, -1351455249}, {1651075262, -1373184801},
+{1632959377, -1394679064}, {1614563692, -1415934356},
+{1595891361, -1436947036}, {1576945581, -1457713501},
+{1557729600, -1478230195}, {1538246711, -1498493602},
+{1518500250, -1518500250}, {1498493602, -1538246711},
+{1478230195, -1557729600}, {1457713501, -1576945581},
+{1436947036, -1595891361}, {1415934356, -1614563692},
+{1394679064, -1632959377}, {1373184801, -1651075262},
+{1351455249, -1668908244}, {1329494133, -1686455268},
+{1307305214, -1703713325}, {1284892296, -1720679461},
+{1262259218, -1737350766}, {1239409858, -1753724386},
+{1216348132, -1769797514}, {1193077991, -1785567396},
+{1169603422, -1801031331}, {1145928447, -1816186668},
+{1122057124, -1831030811}, {1097993542, -1845561216},
+{1073741824, -1859775393}, {1049306126, -1873670908},
+{1024690635, -1887245379}, {999899569, -1900496480},
+{974937175, -1913421941}, {949807730, -1926019547},
+{924515541, -1938287139}, {899064940, -1950222616},
+{873460290, -1961823932}, {847705977, -1973089100},
+{821806413, -1984016189}, {795766038, -1994603327},
+{769589312, -2004848700}, {743280720, -2014750553},
+{716844772, -2024307188}, {690285996, -2033516969},
+{663608942, -2042378317}, {636818183, -2050889714},
+{609918309, -2059049702}, {582913927, -2066856882},
+{555809667, -2074309917}, {528610172, -2081407530},
+{501320102, -2088148504}, {473944133, -2094531684},
+{446486956, -2100555978}, {418953276, -2106220352},
+{391347811, -2111523836}, {363675290, -2116465521},
+{335940456, -2121044561}, {308148059, -2125260170},
+{280302863, -2129111628}, {252409639, -2132598273},
+{224473166, -2135719508}, {196498230, -2138474799},
+{168489625, -2140863673}, {140452151, -2142885721},
+{112390610, -2144540596}, {84309812, -2145828016},
+{56214568, -2146747759}, {28109692, -2147299668},
+{0, -2147483648}, {-28109692, -2147299668},
+{-56214568, -2146747759}, {-84309812, -2145828016},
+{-112390610, -2144540596}, {-140452151, -2142885721},
+{-168489625, -2140863673}, {-196498230, -2138474799},
+{-224473166, -2135719508}, {-252409639, -2132598273},
+{-280302863, -2129111628}, {-308148059, -2125260170},
+{-335940456, -2121044561}, {-363675290, -2116465521},
+{-391347811, -2111523836}, {-418953276, -2106220352},
+{-446486956, -2100555978}, {-473944133, -2094531684},
+{-501320102, -2088148504}, {-528610172, -2081407530},
+{-555809667, -2074309917}, {-582913927, -2066856882},
+{-609918309, -2059049702}, {-636818183, -2050889714},
+{-663608942, -2042378317}, {-690285996, -2033516969},
+{-716844772, -2024307188}, {-743280720, -2014750553},
+{-769589312, -2004848700}, {-795766038, -1994603327},
+{-821806413, -1984016189}, {-847705977, -1973089100},
+{-873460290, -1961823932}, {-899064940, -1950222616},
+{-924515541, -1938287139}, {-949807730, -1926019547},
+{-974937175, -1913421941}, {-999899569, -1900496480},
+{-1024690635, -1887245379}, {-1049306126, -1873670908},
+{-1073741824, -1859775393}, {-1097993542, -1845561216},
+{-1122057124, -1831030811}, {-1145928447, -1816186668},
+{-1169603422, -1801031331}, {-1193077991, -1785567396},
+{-1216348132, -1769797514}, {-1239409858, -1753724386},
+{-1262259218, -1737350766}, {-1284892296, -1720679461},
+{-1307305214, -1703713325}, {-1329494133, -1686455268},
+{-1351455249, -1668908244}, {-1373184801, -1651075262},
+{-1394679064, -1632959377}, {-1415934356, -1614563692},
+{-1436947036, -1595891361}, {-1457713501, -1576945581},
+{-1478230195, -1557729600}, {-1498493602, -1538246711},
+{-1518500250, -1518500250}, {-1538246711, -1498493602},
+{-1557729600, -1478230195}, {-1576945581, -1457713501},
+{-1595891361, -1436947036}, {-1614563692, -1415934356},
+{-1632959377, -1394679064}, {-1651075262, -1373184801},
+{-1668908244, -1351455249}, {-1686455268, -1329494133},
+{-1703713325, -1307305214}, {-1720679461, -1284892296},
+{-1737350766, -1262259218}, {-1753724386, -1239409858},
+{-1769797514, -1216348132}, {-1785567396, -1193077991},
+{-1801031331, -1169603422}, {-1816186668, -1145928447},
+{-1831030811, -1122057124}, {-1845561216, -1097993542},
+{-1859775393, -1073741824}, {-1873670908, -1049306126},
+{-1887245379, -1024690635}, {-1900496480, -999899569},
+{-1913421941, -974937175}, {-1926019547, -949807730},
+{-1938287139, -924515541}, {-1950222616, -899064940},
+{-1961823932, -873460290}, {-1973089100, -847705977},
+{-1984016189, -821806413}, {-1994603327, -795766038},
+{-2004848700, -769589312}, {-2014750553, -743280720},
+{-2024307188, -716844772}, {-2033516969, -690285996},
+{-2042378317, -663608942}, {-2050889714, -636818183},
+{-2059049702, -609918309}, {-2066856882, -582913927},
+{-2074309917, -555809667}, {-2081407530, -528610172},
+{-2088148504, -501320102}, {-2094531684, -473944133},
+{-2100555978, -446486956}, {-2106220352, -418953276},
+{-2111523836, -391347811}, {-2116465521, -363675290},
+{-2121044561, -335940456}, {-2125260170, -308148059},
+{-2129111628, -280302863}, {-2132598273, -252409639},
+{-2135719508, -224473166}, {-2138474799, -196498230},
+{-2140863673, -168489625}, {-2142885721, -140452151},
+{-2144540596, -112390610}, {-2145828016, -84309812},
+{-2146747759, -56214568}, {-2147299668, -28109692},
+{-2147483648, 0}, {-2147299668, 28109692},
+{-2146747759, 56214568}, {-2145828016, 84309812},
+{-2144540596, 112390610}, {-2142885721, 140452151},
+{-2140863673, 168489625}, {-2138474799, 196498230},
+{-2135719508, 224473166}, {-2132598273, 252409639},
+{-2129111628, 280302863}, {-2125260170, 308148059},
+{-2121044561, 335940456}, {-2116465521, 363675290},
+{-2111523836, 391347811}, {-2106220352, 418953276},
+{-2100555978, 446486956}, {-2094531684, 473944133},
+{-2088148504, 501320102}, {-2081407530, 528610172},
+{-2074309917, 555809667}, {-2066856882, 582913927},
+{-2059049702, 609918309}, {-2050889714, 636818183},
+{-2042378317, 663608942}, {-2033516969, 690285996},
+{-2024307188, 716844772}, {-2014750553, 743280720},
+{-2004848700, 769589312}, {-1994603327, 795766038},
+{-1984016189, 821806413}, {-1973089100, 847705977},
+{-1961823932, 873460290}, {-1950222616, 899064940},
+{-1938287139, 924515541}, {-1926019547, 949807730},
+{-1913421941, 974937175}, {-1900496480, 999899569},
+{-1887245379, 1024690635}, {-1873670908, 1049306126},
+{-1859775393, 1073741824}, {-1845561216, 1097993542},
+{-1831030811, 1122057124}, {-1816186668, 1145928447},
+{-1801031331, 1169603422}, {-1785567396, 1193077991},
+{-1769797514, 1216348132}, {-1753724386, 1239409858},
+{-1737350766, 1262259218}, {-1720679461, 1284892296},
+{-1703713325, 1307305214}, {-1686455268, 1329494133},
+{-1668908244, 1351455249}, {-1651075262, 1373184801},
+{-1632959377, 1394679064}, {-1614563692, 1415934356},
+{-1595891361, 1436947036}, {-1576945581, 1457713501},
+{-1557729600, 1478230195}, {-1538246711, 1498493602},
+{-1518500250, 1518500250}, {-1498493602, 1538246711},
+{-1478230195, 1557729600}, {-1457713501, 1576945581},
+{-1436947036, 1595891361}, {-1415934356, 1614563692},
+{-1394679064, 1632959377}, {-1373184801, 1651075262},
+{-1351455249, 1668908244}, {-1329494133, 1686455268},
+{-1307305214, 1703713325}, {-1284892296, 1720679461},
+{-1262259218, 1737350766}, {-1239409858, 1753724386},
+{-1216348132, 1769797514}, {-1193077991, 1785567396},
+{-1169603422, 1801031331}, {-1145928447, 1816186668},
+{-1122057124, 1831030811}, {-1097993542, 1845561216},
+{-1073741824, 1859775393}, {-1049306126, 1873670908},
+{-1024690635, 1887245379}, {-999899569, 1900496480},
+{-974937175, 1913421941}, {-949807730, 1926019547},
+{-924515541, 1938287139}, {-899064940, 1950222616},
+{-873460290, 1961823932}, {-847705977, 1973089100},
+{-821806413, 1984016189}, {-795766038, 1994603327},
+{-769589312, 2004848700}, {-743280720, 2014750553},
+{-716844772, 2024307188}, {-690285996, 2033516969},
+{-663608942, 2042378317}, {-636818183, 2050889714},
+{-609918309, 2059049702}, {-582913927, 2066856882},
+{-555809667, 2074309917}, {-528610172, 2081407530},
+{-501320102, 2088148504}, {-473944133, 2094531684},
+{-446486956, 2100555978}, {-418953276, 2106220352},
+{-391347811, 2111523836}, {-363675290, 2116465521},
+{-335940456, 2121044561}, {-308148059, 2125260170},
+{-280302863, 2129111628}, {-252409639, 2132598273},
+{-224473166, 2135719508}, {-196498230, 2138474799},
+{-168489625, 2140863673}, {-140452151, 2142885721},
+{-112390610, 2144540596}, {-84309812, 2145828016},
+{-56214568, 2146747759}, {-28109692, 2147299668},
+{0, 2147483647}, {28109692, 2147299668},
+{56214568, 2146747759}, {84309812, 2145828016},
+{112390610, 2144540596}, {140452151, 2142885721},
+{168489625, 2140863673}, {196498230, 2138474799},
+{224473166, 2135719508}, {252409639, 2132598273},
+{280302863, 2129111628}, {308148059, 2125260170},
+{335940456, 2121044561}, {363675290, 2116465521},
+{391347811, 2111523836}, {418953276, 2106220352},
+{446486956, 2100555978}, {473944133, 2094531684},
+{501320102, 2088148504}, {528610172, 2081407530},
+{555809667, 2074309917}, {582913927, 2066856882},
+{609918309, 2059049702}, {636818183, 2050889714},
+{663608942, 2042378317}, {690285996, 2033516969},
+{716844772, 2024307188}, {743280720, 2014750553},
+{769589312, 2004848700}, {795766038, 1994603327},
+{821806413, 1984016189}, {847705977, 1973089100},
+{873460290, 1961823932}, {899064940, 1950222616},
+{924515541, 1938287139}, {949807730, 1926019547},
+{974937175, 1913421941}, {999899569, 1900496480},
+{1024690635, 1887245379}, {1049306126, 1873670908},
+{1073741824, 1859775393}, {1097993542, 1845561216},
+{1122057124, 1831030811}, {1145928447, 1816186668},
+{1169603422, 1801031331}, {1193077991, 1785567396},
+{1216348132, 1769797514}, {1239409858, 1753724386},
+{1262259218, 1737350766}, {1284892296, 1720679461},
+{1307305214, 1703713325}, {1329494133, 1686455268},
+{1351455249, 1668908244}, {1373184801, 1651075262},
+{1394679064, 1632959377}, {1415934356, 1614563692},
+{1436947036, 1595891361}, {1457713501, 1576945581},
+{1478230195, 1557729600}, {1498493602, 1538246711},
+{1518500250, 1518500250}, {1538246711, 1498493602},
+{1557729600, 1478230195}, {1576945581, 1457713501},
+{1595891361, 1436947036}, {1614563692, 1415934356},
+{1632959377, 1394679064}, {1651075262, 1373184801},
+{1668908244, 1351455249}, {1686455268, 1329494133},
+{1703713325, 1307305214}, {1720679461, 1284892296},
+{1737350766, 1262259218}, {1753724386, 1239409858},
+{1769797514, 1216348132}, {1785567396, 1193077991},
+{1801031331, 1169603422}, {1816186668, 1145928447},
+{1831030811, 1122057124}, {1845561216, 1097993542},
+{1859775393, 1073741824}, {1873670908, 1049306126},
+{1887245379, 1024690635}, {1900496480, 999899569},
+{1913421941, 974937175}, {1926019547, 949807730},
+{1938287139, 924515541}, {1950222616, 899064940},
+{1961823932, 873460290}, {1973089100, 847705977},
+{1984016189, 821806413}, {1994603327, 795766038},
+{2004848700, 769589312}, {2014750553, 743280720},
+{2024307188, 716844772}, {2033516969, 690285996},
+{2042378317, 663608942}, {2050889714, 636818183},
+{2059049702, 609918309}, {2066856882, 582913927},
+{2074309917, 555809667}, {2081407530, 528610172},
+{2088148504, 501320102}, {2094531684, 473944133},
+{2100555978, 446486956}, {2106220352, 418953276},
+{2111523836, 391347811}, {2116465521, 363675290},
+{2121044561, 335940456}, {2125260170, 308148059},
+{2129111628, 280302863}, {2132598273, 252409639},
+{2135719508, 224473166}, {2138474799, 196498230},
+{2140863673, 168489625}, {2142885721, 140452151},
+{2144540596, 112390610}, {2145828016, 84309812},
+{2146747759, 56214568}, {2147299668, 28109692},
+#else
+{32767, 0}, {32765, -429},
+{32757, -858}, {32743, -1286},
+{32723, -1715}, {32698, -2143},
+{32667, -2571}, {32631, -2998},
+{32588, -3425}, {32541, -3851},
+{32488, -4277}, {32429, -4702},
+{32365, -5126}, {32295, -5549},
+{32219, -5971}, {32138, -6393},
+{32052, -6813}, {31960, -7232},
+{31863, -7650}, {31760, -8066},
+{31651, -8481}, {31538, -8895},
+{31419, -9307}, {31294, -9717},
+{31164, -10126}, {31029, -10533},
+{30888, -10938}, {30743, -11342},
+{30592, -11743}, {30435, -12142},
+{30274, -12540}, {30107, -12935},
+{29935, -13328}, {29758, -13719},
+{29576, -14107}, {29389, -14493},
+{29197, -14876}, {28999, -15257},
+{28797, -15636}, {28590, -16011},
+{28378, -16384}, {28161, -16754},
+{27939, -17121}, {27713, -17485},
+{27482, -17847}, {27246, -18205},
+{27005, -18560}, {26760, -18912},
+{26510, -19261}, {26255, -19606},
+{25997, -19948}, {25733, -20286},
+{25466, -20622}, {25193, -20953},
+{24917, -21281}, {24636, -21605},
+{24351, -21926}, {24062, -22243},
+{23769, -22556}, {23472, -22865},
+{23170, -23170}, {22865, -23472},
+{22556, -23769}, {22243, -24062},
+{21926, -24351}, {21605, -24636},
+{21281, -24917}, {20953, -25193},
+{20622, -25466}, {20286, -25733},
+{19948, -25997}, {19606, -26255},
+{19261, -26510}, {18912, -26760},
+{18560, -27005}, {18205, -27246},
+{17847, -27482}, {17485, -27713},
+{17121, -27939}, {16754, -28161},
+{16384, -28378}, {16011, -28590},
+{15636, -28797}, {15257, -28999},
+{14876, -29197}, {14493, -29389},
+{14107, -29576}, {13719, -29758},
+{13328, -29935}, {12935, -30107},
+{12540, -30274}, {12142, -30435},
+{11743, -30592}, {11342, -30743},
+{10938, -30888}, {10533, -31029},
+{10126, -31164}, {9717, -31294},
+{9307, -31419}, {8895, -31538},
+{8481, -31651}, {8066, -31760},
+{7650, -31863}, {7232, -31960},
+{6813, -32052}, {6393, -32138},
+{5971, -32219}, {5549, -32295},
+{5126, -32365}, {4702, -32429},
+{4277, -32488}, {3851, -32541},
+{3425, -32588}, {2998, -32631},
+{2571, -32667}, {2143, -32698},
+{1715, -32723}, {1286, -32743},
+{858, -32757}, {429, -32765},
+{0, -32767}, {-429, -32765},
+{-858, -32757}, {-1286, -32743},
+{-1715, -32723}, {-2143, -32698},
+{-2571, -32667}, {-2998, -32631},
+{-3425, -32588}, {-3851, -32541},
+{-4277, -32488}, {-4702, -32429},
+{-5126, -32365}, {-5549, -32295},
+{-5971, -32219}, {-6393, -32138},
+{-6813, -32052}, {-7232, -31960},
+{-7650, -31863}, {-8066, -31760},
+{-8481, -31651}, {-8895, -31538},
+{-9307, -31419}, {-9717, -31294},
+{-10126, -31164}, {-10533, -31029},
+{-10938, -30888}, {-11342, -30743},
+{-11743, -30592}, {-12142, -30435},
+{-12540, -30274}, {-12935, -30107},
+{-13328, -29935}, {-13719, -29758},
+{-14107, -29576}, {-14493, -29389},
+{-14876, -29197}, {-15257, -28999},
+{-15636, -28797}, {-16011, -28590},
+{-16384, -28378}, {-16754, -28161},
+{-17121, -27939}, {-17485, -27713},
+{-17847, -27482}, {-18205, -27246},
+{-18560, -27005}, {-18912, -26760},
+{-19261, -26510}, {-19606, -26255},
+{-19948, -25997}, {-20286, -25733},
+{-20622, -25466}, {-20953, -25193},
+{-21281, -24917}, {-21605, -24636},
+{-21926, -24351}, {-22243, -24062},
+{-22556, -23769}, {-22865, -23472},
+{-23170, -23170}, {-23472, -22865},
+{-23769, -22556}, {-24062, -22243},
+{-24351, -21926}, {-24636, -21605},
+{-24917, -21281}, {-25193, -20953},
+{-25466, -20622}, {-25733, -20286},
+{-25997, -19948}, {-26255, -19606},
+{-26510, -19261}, {-26760, -18912},
+{-27005, -18560}, {-27246, -18205},
+{-27482, -17847}, {-27713, -17485},
+{-27939, -17121}, {-28161, -16754},
+{-28378, -16384}, {-28590, -16011},
+{-28797, -15636}, {-28999, -15257},
+{-29197, -14876}, {-29389, -14493},
+{-29576, -14107}, {-29758, -13719},
+{-29935, -13328}, {-30107, -12935},
+{-30274, -12540}, {-30435, -12142},
+{-30592, -11743}, {-30743, -11342},
+{-30888, -10938}, {-31029, -10533},
+{-31164, -10126}, {-31294, -9717},
+{-31419, -9307}, {-31538, -8895},
+{-31651, -8481}, {-31760, -8066},
+{-31863, -7650}, {-31960, -7232},
+{-32052, -6813}, {-32138, -6393},
+{-32219, -5971}, {-32295, -5549},
+{-32365, -5126}, {-32429, -4702},
+{-32488, -4277}, {-32541, -3851},
+{-32588, -3425}, {-32631, -2998},
+{-32667, -2571}, {-32698, -2143},
+{-32723, -1715}, {-32743, -1286},
+{-32757, -858}, {-32765, -429},
+{-32767, 0}, {-32765, 429},
+{-32757, 858}, {-32743, 1286},
+{-32723, 1715}, {-32698, 2143},
+{-32667, 2571}, {-32631, 2998},
+{-32588, 3425}, {-32541, 3851},
+{-32488, 4277}, {-32429, 4702},
+{-32365, 5126}, {-32295, 5549},
+{-32219, 5971}, {-32138, 6393},
+{-32052, 6813}, {-31960, 7232},
+{-31863, 7650}, {-31760, 8066},
+{-31651, 8481}, {-31538, 8895},
+{-31419, 9307}, {-31294, 9717},
+{-31164, 10126}, {-31029, 10533},
+{-30888, 10938}, {-30743, 11342},
+{-30592, 11743}, {-30435, 12142},
+{-30274, 12540}, {-30107, 12935},
+{-29935, 13328}, {-29758, 13719},
+{-29576, 14107}, {-29389, 14493},
+{-29197, 14876}, {-28999, 15257},
+{-28797, 15636}, {-28590, 16011},
+{-28378, 16384}, {-28161, 16754},
+{-27939, 17121}, {-27713, 17485},
+{-27482, 17847}, {-27246, 18205},
+{-27005, 18560}, {-26760, 18912},
+{-26510, 19261}, {-26255, 19606},
+{-25997, 19948}, {-25733, 20286},
+{-25466, 20622}, {-25193, 20953},
+{-24917, 21281}, {-24636, 21605},
+{-24351, 21926}, {-24062, 22243},
+{-23769, 22556}, {-23472, 22865},
+{-23170, 23170}, {-22865, 23472},
+{-22556, 23769}, {-22243, 24062},
+{-21926, 24351}, {-21605, 24636},
+{-21281, 24917}, {-20953, 25193},
+{-20622, 25466}, {-20286, 25733},
+{-19948, 25997}, {-19606, 26255},
+{-19261, 26510}, {-18912, 26760},
+{-18560, 27005}, {-18205, 27246},
+{-17847, 27482}, {-17485, 27713},
+{-17121, 27939}, {-16754, 28161},
+{-16384, 28378}, {-16011, 28590},
+{-15636, 28797}, {-15257, 28999},
+{-14876, 29197}, {-14493, 29389},
+{-14107, 29576}, {-13719, 29758},
+{-13328, 29935}, {-12935, 30107},
+{-12540, 30274}, {-12142, 30435},
+{-11743, 30592}, {-11342, 30743},
+{-10938, 30888}, {-10533, 31029},
+{-10126, 31164}, {-9717, 31294},
+{-9307, 31419}, {-8895, 31538},
+{-8481, 31651}, {-8066, 31760},
+{-7650, 31863}, {-7232, 31960},
+{-6813, 32052}, {-6393, 32138},
+{-5971, 32219}, {-5549, 32295},
+{-5126, 32365}, {-4702, 32429},
+{-4277, 32488}, {-3851, 32541},
+{-3425, 32588}, {-2998, 32631},
+{-2571, 32667}, {-2143, 32698},
+{-1715, 32723}, {-1286, 32743},
+{-858, 32757}, {-429, 32765},
+{0, 32767}, {429, 32765},
+{858, 32757}, {1286, 32743},
+{1715, 32723}, {2143, 32698},
+{2571, 32667}, {2998, 32631},
+{3425, 32588}, {3851, 32541},
+{4277, 32488}, {4702, 32429},
+{5126, 32365}, {5549, 32295},
+{5971, 32219}, {6393, 32138},
+{6813, 32052}, {7232, 31960},
+{7650, 31863}, {8066, 31760},
+{8481, 31651}, {8895, 31538},
+{9307, 31419}, {9717, 31294},
+{10126, 31164}, {10533, 31029},
+{10938, 30888}, {11342, 30743},
+{11743, 30592}, {12142, 30435},
+{12540, 30274}, {12935, 30107},
+{13328, 29935}, {13719, 29758},
+{14107, 29576}, {14493, 29389},
+{14876, 29197}, {15257, 28999},
+{15636, 28797}, {16011, 28590},
+{16384, 28378}, {16754, 28161},
+{17121, 27939}, {17485, 27713},
+{17847, 27482}, {18205, 27246},
+{18560, 27005}, {18912, 26760},
+{19261, 26510}, {19606, 26255},
+{19948, 25997}, {20286, 25733},
+{20622, 25466}, {20953, 25193},
+{21281, 24917}, {21605, 24636},
+{21926, 24351}, {22243, 24062},
+{22556, 23769}, {22865, 23472},
+{23170, 23170}, {23472, 22865},
+{23769, 22556}, {24062, 22243},
+{24351, 21926}, {24636, 21605},
+{24917, 21281}, {25193, 20953},
+{25466, 20622}, {25733, 20286},
+{25997, 19948}, {26255, 19606},
+{26510, 19261}, {26760, 18912},
+{27005, 18560}, {27246, 18205},
+{27482, 17847}, {27713, 17485},
+{27939, 17121}, {28161, 16754},
+{28378, 16384}, {28590, 16011},
+{28797, 15636}, {28999, 15257},
+{29197, 14876}, {29389, 14493},
+{29576, 14107}, {29758, 13719},
+{29935, 13328}, {30107, 12935},
+{30274, 12540}, {30435, 12142},
+{30592, 11743}, {30743, 11342},
+{30888, 10938}, {31029, 10533},
+{31164, 10126}, {31294, 9717},
+{31419, 9307}, {31538, 8895},
+{31651, 8481}, {31760, 8066},
+{31863, 7650}, {31960, 7232},
+{32052, 6813}, {32138, 6393},
+{32219, 5971}, {32295, 5549},
+{32365, 5126}, {32429, 4702},
+{32488, 4277}, {32541, 3851},
+{32588, 3425}, {32631, 2998},
+{32667, 2571}, {32698, 2143},
+{32723, 1715}, {32743, 1286},
+{32757, 858}, {32765, 429},
+#endif
+};
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_BITREV60
+#define FFT_BITREV60
+static const opus_int16 fft_bitrev60[60] = {
+0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
+1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
+2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
+3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
+};
+#endif
+
+#ifndef FFT_STATE48000_960_0
+#define FFT_STATE48000_960_0
+static const kiss_fft_state fft_state48000_960_0 = {
+480,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+8,    /* scale_shift */
+-1,    /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev480,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_1
+#define FFT_STATE48000_960_1
+static const kiss_fft_state fft_state48000_960_1 = {
+240,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+7,    /* scale_shift */
+1,    /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev240,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_2
+#define FFT_STATE48000_960_2
+static const kiss_fft_state fft_state48000_960_2 = {
+120,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+6,    /* scale_shift */
+2,    /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev120,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_3
+#define FFT_STATE48000_960_3
+static const kiss_fft_state fft_state48000_960_3 = {
+60,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+5,    /* scale_shift */
+3,    /* shift */
+{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev60,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_60,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES960
+#define MDCT_TWIDDLES960
+static const celt_coef mdct_twiddles960[1800] = {
+#ifdef ENABLE_QEXT
+2147483468, 2147469095, 2147431723, 2147371355, 2147287990,
+2147181629, 2147052273, 2146899924, 2146724584, 2146526254,
+2146304937, 2146060634, 2145793349, 2145503083, 2145189842,
+2144853627, 2144494442, 2144112292, 2143707180, 2143279110,
+2142828088, 2142354118, 2141857204, 2141337354, 2140794571,
+2140228862, 2139640233, 2139028690, 2138394240, 2137736889,
+2137056645, 2136353515, 2135627506, 2134878626, 2134106884,
+2133312286, 2132494843, 2131654563, 2130791454, 2129905526,
+2128996788, 2128065251, 2127110924, 2126133817, 2125133941,
+2124111307, 2123065925, 2121997806, 2120906963, 2119793407,
+2118657149, 2117498202, 2116316578, 2115112291, 2113885352,
+2112635775, 2111363574, 2110068761, 2108751352, 2107411359,
+2106048798, 2104663683, 2103256028, 2101825849, 2100373162,
+2098897981, 2097400322, 2095880202, 2094337637, 2092772643,
+2091185237, 2089575437, 2087943258, 2086288720, 2084611839,
+2082912633, 2081191122, 2079447322, 2077681253, 2075892934,
+2074082383, 2072249621, 2070394667, 2068517540, 2066618262,
+2064696851, 2062753329, 2060787717, 2058800036, 2056790306,
+2054758550, 2052704789, 2050629045, 2048531340, 2046411698,
+2044270140, 2042106689, 2039921369, 2037714204, 2035485216,
+2033234429, 2030961869, 2028667558, 2026351522, 2024013785,
+2021654373, 2019273310, 2016870623, 2014446336, 2012000477,
+2009533071, 2007044144, 2004533723, 2002001835, 1999448508,
+1996873768, 1994277643, 1991660161, 1989021350, 1986361238,
+1983679853, 1980977226, 1978253383, 1975508355, 1972742171,
+1969954860, 1967146453, 1964316979, 1961466469, 1958594953,
+1955702462, 1952789027, 1949854680, 1946899451, 1943923372,
+1940926475, 1937908793, 1934870357, 1931811201, 1928731356,
+1925630856, 1922509734, 1919368023, 1916205758, 1913022972,
+1909819698, 1906595972, 1903351828, 1900087301, 1896802425,
+1893497236, 1890171769, 1886826060, 1883460144, 1880074058,
+1876667838, 1873241521, 1869795142, 1866328740, 1862842350,
+1859336011, 1855809760, 1852263635, 1848697674, 1845111914,
+1841506395, 1837881155, 1834236233, 1830571667, 1826887497,
+1823183763, 1819460504, 1815717761, 1811955572, 1808173978,
+1804373021, 1800552740, 1796713177, 1792854372, 1788976368,
+1785079205, 1781162925, 1777227570, 1773273182, 1769299805,
+1765307479, 1761296249, 1757266156, 1753217244, 1749149557,
+1745063138, 1740958031, 1736834279, 1732691928, 1728531020,
+1724351602, 1720153717, 1715937410, 1711702727, 1707449714,
+1703178415, 1698888876, 1694581143, 1690255263, 1685911282,
+1681549245, 1677169201, 1672771196, 1668355276, 1663921490,
+1659469885, 1655000508, 1650513407, 1646008631, 1641486227,
+1636946244, 1632388731, 1627813736, 1623221309, 1618611498,
+1613984353, 1609339924, 1604678260, 1599999411, 1595303428,
+1590590360, 1585860258, 1581113173, 1576349155, 1571568256,
+1566770527, 1561956018, 1557124783, 1552276872, 1547412337,
+1542531231, 1537633606, 1532719513, 1527789007, 1522842139,
+1517878963, 1512899531, 1507903898, 1502892116, 1497864239,
+1492820322, 1487760417, 1482684580, 1477592864, 1472485325,
+1467362016, 1462222994, 1457068312, 1451898025, 1446712191,
+1441510863, 1436294098, 1431061951, 1425814478, 1420551737,
+1415273782, 1409980671, 1404672460, 1399349206, 1394010966,
+1388657798, 1383289758, 1377906904, 1372509294, 1367096986,
+1361670037, 1356228505, 1350772450, 1345301929, 1339817000,
+1334317724, 1328804158, 1323276361, 1317734393, 1312178313,
+1306608181, 1301024057, 1295425999, 1289814068, 1284188325,
+1278548828, 1272895640, 1267228820, 1261548429, 1255854528,
+1250147177, 1244426439, 1238692373, 1232945043, 1227184508,
+1221410831, 1215624074, 1209824299, 1204011567, 1198185941,
+1192347484, 1186496258, 1180632325, 1174755748, 1168866591,
+1162964917, 1157050787, 1151124267, 1145185419, 1139234307,
+1133270995, 1127295547, 1121308026, 1115308496, 1109297023,
+1103273670, 1097238502, 1091191583, 1085132978, 1079062753,
+1072980972, 1066887699, 1060783002, 1054666944, 1048539592,
+1042401010, 1036251266, 1030090423, 1023918550, 1017735711,
+1011541973, 1005337402, 999122065, 992896028, 986659358,
+980412122, 974154386, 967886217, 961607684, 955318852,
+949019790, 942710564, 936391243, 930061894, 923722585,
+917373383, 911014357, 904645574, 898267104, 891879014,
+885481373, 879074249, 872657710, 866231826, 859796666,
+853352298, 846898791, 840436214, 833964638, 827484130,
+820994760, 814496598, 807989714, 801474176, 794950056,
+788417422, 781876345, 775326894, 768769141, 762203154,
+755629005, 749046764, 742456501, 735858287, 729252193,
+722638289, 716016646, 709387335, 702750427, 696105993,
+689454104, 682794832, 676128248, 669454423, 662773428,
+656085336, 649390218, 642688145, 635979190, 629263424,
+622540918, 615811746, 609075979, 602333690, 595584950,
+588829831, 582068407, 575300749, 568526931, 561747023,
+554961100, 548169234, 541371497, 534567963, 527758704,
+520943793, 514123303, 507297307, 500465878, 493629090,
+486787016, 479939728, 473087301, 466229807, 459367320,
+452499914, 445627662, 438750638, 431868915, 424982567,
+418091668, 411196291, 404296511, 397392401, 390484035,
+383571488, 376654833, 369734144, 362809495, 355880961,
+348948616, 342012534, 335072790, 328129457, 321182610,
+314232323, 307278671, 300321729, 293361570, 286398270,
+279431902, 272462542, 265490265, 258515144, 251537254,
+244556671, 237573469, 230587722, 223599506, 216608896,
+209615966, 202620791, 195623446, 188624006, 181622546,
+174619141, 167613866, 160606796, 153598006, 146587571,
+139575567, 132562067, 125547148, 118530885, 111513352,
+104494625, 97474778, 90453888, 83432030, 76409277,
+69385707, 62361393, 55336412, 48310838, 41284746,
+34258213, 27231312, 20204120, 13176712, 6149162,
+-878453, -7906059, -14933580, -21960942, -28988068,
+-36014884, -43041314, -50067283, -57092716, -64117537,
+-71141672, -78165045, -85187581, -92209205, -99229841,
+-106249414, -113267850, -120285073, -127301007, -134315578,
+-141328711, -148340330, -155350361, -162358728, -169365356,
+-176370170, -183373096, -190374058, -197372981, -204369791,
+-211364411, -218356769, -225346788, -232334393, -239319511,
+-246302065, -253281982, -260259186, -267233603, -274205159,
+-281173778, -288139385, -295101907, -302061269, -309017396,
+-315970213, -322919647, -329865622, -336808065, -343746901,
+-350682056, -357613455, -364541025, -371464690, -378384377,
+-385300013, -392211522, -399118830, -406021865, -412920551,
+-419814815, -426704583, -433589782, -440470337, -447346176,
+-454217223, -461083406, -467944652, -474800886, -481652035,
+-488498026, -495338786, -502174241, -509004318, -515828944,
+-522648046, -529461551, -536269386, -543071478, -549867754,
+-556658141, -563442567, -570220959, -576993244, -583759350,
+-590519205, -597272736, -604019870, -610760536, -617494660,
+-624222173, -630943000, -637657070, -644364312, -651064652,
+-657758021, -664444345, -671123554, -677795576, -684460338,
+-691117771, -697767803, -704410362, -711045377, -717672778,
+-724292493, -730904451, -737508582, -744104815, -750693079,
+-757273304, -763845419, -770409354, -776965038, -783512402,
+-790051375, -796581887, -803103868, -809617249, -816121959,
+-822617929, -829105090, -835583372, -842052705, -848513021,
+-854964249, -861406322, -867839170, -874262724, -880676915,
+-887081675, -893476935, -899862626, -906238681, -912605031,
+-918961607, -925308342, -931645168, -937972016, -944288820,
+-950595511, -956892022, -963178285, -969454234, -975719800,
+-981974918, -988219519, -994453537, -1000676905, -1006889557,
+-1013091426, -1019282445, -1025462549, -1031631671, -1037789745,
+-1043936705, -1050072485, -1056197020, -1062310244, -1068412091,
+-1074502497, -1080581395, -1086648722, -1092704411, -1098748398,
+-1104780618, -1110801008, -1116809501, -1122806034, -1128790543,
+-1134762964, -1140723232, -1146671283, -1152607055, -1158530484,
+-1164441505, -1170340057, -1176226074, -1182099496, -1187960258,
+-1193808298, -1199643553, -1205465961, -1211275460, -1217071986,
+-1222855479, -1228625876, -1234383115, -1240127136, -1245857875,
+-1251575272, -1257279266, -1262969796, -1268646800, -1274310217,
+-1279959989, -1285596052, -1291218348, -1296826816, -1302421396,
+-1308002029, -1313568653, -1319121210, -1324659641, -1330183885,
+-1335693885, -1341189580, -1346670912, -1352137822, -1357590252,
+-1363028143, -1368451438, -1373860077, -1379254004, -1384633159,
+-1389997487, -1395346928, -1400681427, -1406000925, -1411305366,
+-1416594694, -1421868850, -1427127780, -1432371426, -1437599733,
+-1442812644, -1448010104, -1453192057, -1458358447, -1463509220,
+-1468644319, -1473763690, -1478867279, -1483955030, -1489026889,
+-1494082802, -1499122714, -1504146572, -1509154322, -1514145910,
+-1519121283, -1524080387, -1529023170, -1533949577, -1538859558,
+-1543753058, -1548630027, -1553490410, -1558334157, -1563161216,
+-1567971534, -1572765060, -1577541744, -1582301533, -1587044377,
+-1591770225, -1596479027, -1601170732, -1605845289, -1610502649,
+-1615142762, -1619765578, -1624371047, -1628959121, -1633529750,
+-1638082885, -1642618478, -1647136479, -1651636841, -1656119516,
+-1660584454, -1665031609, -1669460933, -1673872378, -1678265898,
+-1682641444, -1686998971, -1691338432, -1695659779, -1699962968,
+-1704247951, -1708514683, -1712763118, -1716993211, -1721204917,
+-1725398189, -1729572984, -1733729257, -1737866963, -1741986057,
+-1746086497, -1750168237, -1754231234, -1758275445, -1762300826,
+-1766307335, -1770294927, -1774263561, -1778213194, -1782143784,
+-1786055289, -1789947667, -1793820875, -1797674873, -1801509620,
+-1805325074, -1809121194, -1812897940, -1816655271, -1820393147,
+-1824111529, -1827810376, -1831489648, -1835149306, -1838789312,
+-1842409625, -1846010208, -1849591022, -1853152028, -1856693188,
+-1860214464, -1863715819, -1867197215, -1870658615, -1874099982,
+-1877521279, -1880922469, -1884303515, -1887664383, -1891005035,
+-1894325435, -1897625550, -1900905342, -1904164776, -1907403819,
+-1910622435, -1913820590, -1916998250, -1920155379, -1923291946,
+-1926407915, -1929503255, -1932577931, -1935631910, -1938665161,
+-1941677650, -1944669345, -1947640214, -1950590226, -1953519348,
+-1956427550, -1959314800, -1962181067, -1965026321, -1967850531,
+-1970653667, -1973435699, -1976196596, -1978936331, -1981654873,
+-1984352192, -1987028261, -1989683050, -1992316532, -1994928677,
+-1997519459, -2000088848, -2002636818, -2005163342, -2007668391,
+-2010151941, -2012613963, -2015054432, -2017473321, -2019870604,
+-2022246257, -2024600252, -2026932566, -2029243173, -2031532049,
+-2033799168, -2036044507, -2038268042, -2040469748, -2042649603,
+-2044807583, -2046943664, -2049057824, -2051150040, -2053220291,
+-2055268553, -2057294804, -2059299024, -2061281190, -2063241282,
+-2065179277, -2067095157, -2068988899, -2070860485, -2072709893,
+-2074537104, -2076342098, -2078124857, -2079885360, -2081623590,
+-2083339527, -2085033153, -2086704450, -2088353400, -2089979985,
+-2091584189, -2093165993, -2094725382, -2096262337, -2097776843,
+-2099268884, -2100738443, -2102185505, -2103610054, -2105012075,
+-2106391553, -2107748474, -2109082822, -2110394584, -2111683744,
+-2112950291, -2114194210, -2115415487, -2116614110, -2117790065,
+-2118943341, -2120073924, -2121181804, -2122266967, -2123329402,
+-2124369098, -2125386044, -2126380229, -2127351642, -2128300272,
+-2129226111, -2130129147, -2131009371, -2131866773, -2132701345,
+-2133513078, -2134301962, -2135067990, -2135811153, -2136531442,
+-2137228852, -2137903373, -2138555000, -2139183723, -2139789539,
+-2140372438, -2140932416, -2141469466, -2141983583, -2142474761,
+-2142942995, -2143388280, -2143810610, -2144209982, -2144586392,
+-2144939834, -2145270306, -2145577804, -2145862324, -2146123864,
+-2146362421, -2146577992, -2146770575, -2146940167, -2147086768,
+-2147210375, -2147310987, -2147388603, -2147443222, -2147474844,
+2147482929, 2147425435, 2147275952, 2147034487, 2146701050,
+2146275656, 2145758322, 2145149071, 2144447929, 2143654926,
+2142770096, 2141793477, 2140725111, 2139565043, 2138313323,
+2136970005, 2135535146, 2134008809, 2132391057, 2130681961,
+2128881593, 2126990031, 2125007356, 2122933653, 2120769010,
+2118513521, 2116167282, 2113730393, 2111202959, 2108585087,
+2105876892, 2103078487, 2100189994, 2097211535, 2094143239,
+2090985237, 2087737664, 2084400659, 2080974365, 2077458929,
+2073854502, 2070161238, 2066379295, 2062508835, 2058550025,
+2054503033, 2050368032, 2046145201, 2041834720, 2037436773,
+2032951550, 2028379241, 2023720043, 2018974156, 2014141783,
+2009223131, 2004218410, 1999127836, 1993951625, 1988690000,
+1983343186, 1977911412, 1972394912, 1966793920, 1961108677,
+1955339428, 1949486417, 1943549898, 1937530123, 1931427351,
+1925241843, 1918973864, 1912623682, 1906191570, 1899677803,
+1893082661, 1886406424, 1879649381, 1872811820, 1865894033,
+1858896318, 1851818974, 1844662304, 1837426615, 1830112217,
+1822719423, 1815248550, 1807699917, 1800073849, 1792370671,
+1784590714, 1776734311, 1768801799, 1760793518, 1752709809,
+1744551021, 1736317502, 1728009604, 1719627685, 1711172102,
+1702643219, 1694041400, 1685367013, 1676620432, 1667802029,
+1658912184, 1649951276, 1640919689, 1631817811, 1622646032,
+1613404744, 1604094343, 1594715227, 1585267800, 1575752465,
+1566169630, 1556519705, 1546803104, 1537020244, 1527171542,
+1517257422, 1507278307, 1497234626, 1487126808, 1476955286,
+1466720497, 1456422878, 1446062871, 1435640919, 1425157469,
+1414612971, 1404007875, 1393342636, 1382617710, 1371833558,
+1360990642, 1350089425, 1339130374, 1328113960, 1317040654,
+1305910930, 1294725265, 1283484138, 1272188032, 1260837429,
+1249432816, 1237974681, 1226463516, 1214899813, 1203284068,
+1191616778, 1179898443, 1168129565, 1156310649, 1144442200,
+1132524727, 1120558740, 1108544752, 1096483278, 1084374834,
+1072219940, 1060019115, 1047772882, 1035481766, 1023146293,
+1010766993, 998344394, 985879030, 973371434, 960822142,
+948231691, 935600622, 922929474, 910218791, 897469118,
+884680999, 871854984, 858991622, 846091463, 833155061,
+820182969, 807175743, 794133941, 781058120, 767948841,
+754806666, 741632158, 728425880, 715188400, 701920283,
+688622098, 675294414, 661937804, 648552838, 635140090,
+621700135, 608233549, 594740907, 581222789, 567679774,
+554112440, 540521371, 526907147, 513270353, 499611571,
+485931388, 472230390, 458509162, 444768294, 431008373,
+417229989, 403433732, 389620194, 375789965, 361943639,
+348081809, 334205068, 320314011, 306409232, 292491328,
+278560894, 264618528, 250664827, 236700388, 222725809,
+208741690, 194748629, 180747225, 166738079, 152721790,
+138698959, 124670187, 110636075, 96597223, 82554233,
+68507707, 54458246, 40406452, 26352928, 12298274,
+-1756906, -15812011, -29866438, -43919586, -57970853,
+-72019637, -86065335, -100107347, -114145071, -128177904,
+-142205248, -156226499, -170241059, -184248325, -198247699,
+-212238581, -226220372, -240192472, -254154282, -268105206,
+-282044645, -295972002, -309886680, -323788084, -337675619,
+-351548688, -365406698, -379249055, -393075166, -406884440,
+-420676284, -434450107, -448205320, -461941333, -475657559,
+-489353409, -503028296, -516681636, -530312842, -543921332,
+-557506522, -571067830, -584604676, -598116479, -611602660,
+-625062643, -638495850, -651901706, -665279637, -678629069,
+-691949432, -705240153, -718500664, -731730397, -744928785,
+-758095263, -771229267, -784330234, -797397602, -810430813,
+-823429308, -836392529, -849319923, -862210934, -875065011,
+-887881603, -900660162, -913400139, -926100989, -938762167,
+-951383133, -963963344, -976502263, -988999351, -1001454074,
+-1013865898, -1026234291, -1038558724, -1050838668, -1063073598,
+-1075262990, -1087406320, -1099503070, -1111552721, -1123554757,
+-1135508663, -1147413928, -1159270041, -1171076495, -1182832785,
+-1194538405, -1206192856, -1217795637, -1229346252, -1240844206,
+-1252289006, -1263680162, -1275017186, -1286299593, -1297526899,
+-1308698624, -1319814288, -1330873416, -1341875533, -1352820169,
+-1363706855, -1374535124, -1385304512, -1396014559, -1406664805,
+-1417254794, -1427784073, -1438252190, -1448658697, -1459003149,
+-1469285102, -1479504115, -1489659751, -1499751576, -1509779156,
+-1519742062, -1529639867, -1539472148, -1549238483, -1558938453,
+-1568571644, -1578137643, -1587636039, -1597066426, -1606428400,
+-1615721561, -1624945509, -1634099849, -1643184191, -1652198144,
+-1661141322, -1670013342, -1678813825, -1687542393, -1696198672,
+-1704782292, -1713292884, -1721730085, -1730093532, -1738382868,
+-1746597738, -1754737789, -1762802673, -1770792044, -1778705561,
+-1786542883, -1794303676, -1801987607, -1809594347, -1817123570,
+-1824574954, -1831948179, -1839242929, -1846458892, -1853595759,
+-1860653224, -1867630985, -1874528743, -1881346202, -1888083070,
+-1894739060, -1901313885, -1907807264, -1914218919, -1920548575,
+-1926795962, -1932960811, -1939042858, -1945041843, -1950957509,
+-1956789602, -1962537873, -1968202076, -1973781967, -1979277308,
+-1984687864, -1990013401, -1995253694, -2000408516, -2005477648,
+-2010460871, -2015357973, -2020168744, -2024892978, -2029530472,
+-2034081027, -2038544449, -2042920547, -2047209133, -2051410023,
+-2055523038, -2059548001, -2063484740, -2067333086, -2071092874,
+-2074763944, -2078346137, -2081839301, -2085243286, -2088557947,
+-2091783140, -2094918728, -2097964577, -2100920556, -2103786539,
+-2106562402, -2109248028, -2111843300, -2114348108, -2116762344,
+-2119085905, -2121318692, -2123460608, -2125511562, -2127471467,
+-2129340237, -2131117794, -2132804061, -2134398966, -2135902440,
+-2137314419, -2138634843, -2139863654, -2141000801, -2142046235,
+-2142999911, -2143861787, -2144631828, -2145310000, -2145896274,
+-2146390624, -2146793031, -2147103476, -2147321946, -2147448433,
+2147480773, 2147250799, 2146652904, 2145687192, 2144353827,
+2142653038, 2140585116, 2138150417, 2135349356, 2132182414,
+2128650133, 2124753120, 2120492040, 2115867626, 2110880668,
+2105532022, 2099822604, 2093753392, 2087325426, 2080539807,
+2073397699, 2065900325, 2058048970, 2049844978, 2041289756,
+2032384769, 2023131544, 2013531666, 2003586779, 1993298588,
+1982668856, 1971699403, 1960392110, 1948748914, 1936771810,
+1924462850, 1911824143, 1898857855, 1885566207, 1871951478,
+1858015999, 1843762158, 1829192399, 1814309216, 1799115162,
+1783612838, 1767804901, 1751694060, 1735283075, 1718574758,
+1701571972, 1684277631, 1666694698, 1648826185, 1630675154,
+1612244715, 1593538026, 1574558293, 1555308768, 1535792748,
+1516013578, 1495974647, 1475679389, 1455131280, 1434333842,
+1413290638, 1392005275, 1370481398, 1348722696, 1326732898,
+1304515771, 1282075122, 1259414796, 1236538675, 1213450681,
+1190154767, 1166654927, 1142955186, 1119059606, 1094972281,
+1070697338, 1046238936, 1021601267, 996788551, 971805042,
+946655018, 921342790, 895872694, 870249095, 844476384,
+818558976, 792501312, 766307857, 739983099, 713531549,
+686957739, 660266222, 633461572, 606548381, 579531262,
+552414843, 525203770, 497902707, 470516330, 443049333,
+415506422, 387892316, 360211746, 332469456, 304670200,
+276818739, 248919847, 220978304, 192998897, 164986421,
+136945676, 108881465, 80798598, 52701887, 24596146,
+-3513810, -31623164, -59727099, -87820801, -115899455,
+-143958250, -171992378, -199997036, -227967426, -255898755,
+-283786237, -311625094, -339410555, -367137861, -394802258,
+-422399009, -449923384, -477370666, -504736154, -532015158,
+-559203003, -586295032, -613286603, -640173090, -666949886,
+-693612404, -720156076, -746576352, -772868706, -799028633,
+-825051651, -850933300, -876669146, -902254780, -927685817,
+-952957899, -978066697, -1003007909, -1027777260, -1052370507,
+-1076783436, -1101011863, -1125051638, -1148898640, -1172548785,
+-1195998020, -1219242327, -1242277723, -1265100260, -1287706030,
+-1310091157, -1332251808, -1354184184, -1375884527, -1397349119,
+-1418574283, -1439556382, -1460291820, -1480777044, -1501008545,
+-1520982856, -1540696555, -1560146263, -1579328647, -1598240423,
+-1616878347, -1635239228, -1653319919, -1671117323, -1688628389,
+-1705850117, -1722779556, -1739413807, -1755750017, -1771785389,
+-1787517174, -1802942678, -1818059257, -1832864320, -1847355332,
+-1861529809, -1875385322, -1888919498, -1902130017, -1915014616,
+-1927571087, -1939797279, -1951691096, -1963250501, -1974473513,
+-1985358210, -1995902725, -2006105253, -2015964045, -2025477412,
+-2034643724, -2043461410, -2051928960, -2060044922, -2067807906,
+-2075216581, -2082269679, -2088965991, -2095304370, -2101283728,
+-2106903043, -2112161350, -2117057750, -2121591402, -2125761531,
+-2129567422, -2133008422, -2136083942, -2138793455, -2141136497,
+-2143112666, -2144721624, -2145963095, -2146836866, -2147342788,
+2147472149, 2146552303, 2144161316, 2140300829, 2134973487,
+2128182940, 2119933843, 2110231849, 2099083608, 2086496759,
+2072479930, 2057042727, 2040195730, 2021950484, 2002319494,
+1981316215, 1958955040, 1935251296, 1910221227, 1883881987,
+1856251629, 1827349089, 1797194176, 1765807555, 1733210737,
+1699426064, 1664476689, 1628386565, 1591180426, 1552883771,
+1513522847, 1473124631, 1431716808, 1389327759, 1345986533,
+1301722835, 1256567002, 1210549980, 1163703308, 1116059092,
+1067649985, 1018509163, 968670307, 918167572, 867035571,
+815309347, 763024350, 710216415, 656921734, 603176830,
+549018540, 494483979, 439610524, 384435782, 328997567,
+273333873, 217482850, 161482775, 105372028, 49189064,
+-7027611, -63239471, -119407989, -175494670, -231461077,
+-287268852, -342879747, -398255649, -453358607, -508150855,
+-562594842, -616653255, -670289044, -723465451, -776146031,
+-828294679, -879875655, -930853609, -981193602, -1030861133,
+-1079822164, -1128043139, -1175491010, -1222133257, -1267937916,
+-1312873593, -1356909492, -1400015434, -1442161874, -1483319929,
+-1523461391, -1562558748, -1600585205, -1637514702, -1673321927,
+-1707982341, -1741472190, -1773768520, -1804849198, -1834692923,
+-1863279241, -1890588560, -1916602164, -1941302225, -1964671814,
+-1986694916, -2007356435, -2026642214, -2044539032, -2061034626,
+-2076117690, -2089777886, -2102005853, -2112793210, -2122132564,
+-2130017514, -2136442657, -2141403589, -2144896910, -2146920225,
+#else
+32767, 32767, 32767, 32766, 32765,
+32763, 32761, 32759, 32756, 32753,
+32750, 32746, 32742, 32738, 32733,
+32728, 32722, 32717, 32710, 32704,
+32697, 32690, 32682, 32674, 32666,
+32657, 32648, 32639, 32629, 32619,
+32609, 32598, 32587, 32576, 32564,
+32552, 32539, 32526, 32513, 32500,
+32486, 32472, 32457, 32442, 32427,
+32411, 32395, 32379, 32362, 32345,
+32328, 32310, 32292, 32274, 32255,
+32236, 32217, 32197, 32177, 32157,
+32136, 32115, 32093, 32071, 32049,
+32027, 32004, 31981, 31957, 31933,
+31909, 31884, 31859, 31834, 31809,
+31783, 31756, 31730, 31703, 31676,
+31648, 31620, 31592, 31563, 31534,
+31505, 31475, 31445, 31415, 31384,
+31353, 31322, 31290, 31258, 31226,
+31193, 31160, 31127, 31093, 31059,
+31025, 30990, 30955, 30920, 30884,
+30848, 30812, 30775, 30738, 30701,
+30663, 30625, 30587, 30548, 30509,
+30470, 30430, 30390, 30350, 30309,
+30269, 30227, 30186, 30144, 30102,
+30059, 30016, 29973, 29930, 29886,
+29842, 29797, 29752, 29707, 29662,
+29616, 29570, 29524, 29477, 29430,
+29383, 29335, 29287, 29239, 29190,
+29142, 29092, 29043, 28993, 28943,
+28892, 28842, 28791, 28739, 28688,
+28636, 28583, 28531, 28478, 28425,
+28371, 28317, 28263, 28209, 28154,
+28099, 28044, 27988, 27932, 27876,
+27820, 27763, 27706, 27648, 27591,
+27533, 27474, 27416, 27357, 27298,
+27238, 27178, 27118, 27058, 26997,
+26936, 26875, 26814, 26752, 26690,
+26628, 26565, 26502, 26439, 26375,
+26312, 26247, 26183, 26119, 26054,
+25988, 25923, 25857, 25791, 25725,
+25658, 25592, 25524, 25457, 25389,
+25322, 25253, 25185, 25116, 25047,
+24978, 24908, 24838, 24768, 24698,
+24627, 24557, 24485, 24414, 24342,
+24270, 24198, 24126, 24053, 23980,
+23907, 23834, 23760, 23686, 23612,
+23537, 23462, 23387, 23312, 23237,
+23161, 23085, 23009, 22932, 22856,
+22779, 22701, 22624, 22546, 22468,
+22390, 22312, 22233, 22154, 22075,
+21996, 21916, 21836, 21756, 21676,
+21595, 21515, 21434, 21352, 21271,
+21189, 21107, 21025, 20943, 20860,
+20777, 20694, 20611, 20528, 20444,
+20360, 20276, 20192, 20107, 20022,
+19937, 19852, 19767, 19681, 19595,
+19509, 19423, 19336, 19250, 19163,
+19076, 18988, 18901, 18813, 18725,
+18637, 18549, 18460, 18372, 18283,
+18194, 18104, 18015, 17925, 17835,
+17745, 17655, 17565, 17474, 17383,
+17292, 17201, 17110, 17018, 16927,
+16835, 16743, 16650, 16558, 16465,
+16372, 16279, 16186, 16093, 15999,
+15906, 15812, 15718, 15624, 15529,
+15435, 15340, 15245, 15150, 15055,
+14960, 14864, 14769, 14673, 14577,
+14481, 14385, 14288, 14192, 14095,
+13998, 13901, 13804, 13706, 13609,
+13511, 13414, 13316, 13218, 13119,
+13021, 12923, 12824, 12725, 12626,
+12527, 12428, 12329, 12230, 12130,
+12030, 11930, 11831, 11730, 11630,
+11530, 11430, 11329, 11228, 11128,
+11027, 10926, 10824, 10723, 10622,
+10520, 10419, 10317, 10215, 10113,
+10011, 9909, 9807, 9704, 9602,
+9499, 9397, 9294, 9191, 9088,
+8985, 8882, 8778, 8675, 8572,
+8468, 8364, 8261, 8157, 8053,
+7949, 7845, 7741, 7637, 7532,
+7428, 7323, 7219, 7114, 7009,
+6905, 6800, 6695, 6590, 6485,
+6380, 6274, 6169, 6064, 5958,
+5853, 5747, 5642, 5536, 5430,
+5325, 5219, 5113, 5007, 4901,
+4795, 4689, 4583, 4476, 4370,
+4264, 4157, 4051, 3945, 3838,
+3732, 3625, 3518, 3412, 3305,
+3198, 3092, 2985, 2878, 2771,
+2664, 2558, 2451, 2344, 2237,
+2130, 2023, 1916, 1809, 1702,
+1594, 1487, 1380, 1273, 1166,
+1059, 952, 844, 737, 630,
+523, 416, 308, 201, 94,
+-13, -121, -228, -335, -442,
+-550, -657, -764, -871, -978,
+-1086, -1193, -1300, -1407, -1514,
+-1621, -1728, -1835, -1942, -2049,
+-2157, -2263, -2370, -2477, -2584,
+-2691, -2798, -2905, -3012, -3118,
+-3225, -3332, -3439, -3545, -3652,
+-3758, -3865, -3971, -4078, -4184,
+-4290, -4397, -4503, -4609, -4715,
+-4821, -4927, -5033, -5139, -5245,
+-5351, -5457, -5562, -5668, -5774,
+-5879, -5985, -6090, -6195, -6301,
+-6406, -6511, -6616, -6721, -6826,
+-6931, -7036, -7140, -7245, -7349,
+-7454, -7558, -7663, -7767, -7871,
+-7975, -8079, -8183, -8287, -8390,
+-8494, -8597, -8701, -8804, -8907,
+-9011, -9114, -9217, -9319, -9422,
+-9525, -9627, -9730, -9832, -9934,
+-10037, -10139, -10241, -10342, -10444,
+-10546, -10647, -10748, -10850, -10951,
+-11052, -11153, -11253, -11354, -11455,
+-11555, -11655, -11756, -11856, -11955,
+-12055, -12155, -12254, -12354, -12453,
+-12552, -12651, -12750, -12849, -12947,
+-13046, -13144, -13242, -13340, -13438,
+-13536, -13633, -13731, -13828, -13925,
+-14022, -14119, -14216, -14312, -14409,
+-14505, -14601, -14697, -14793, -14888,
+-14984, -15079, -15174, -15269, -15364,
+-15459, -15553, -15647, -15741, -15835,
+-15929, -16023, -16116, -16210, -16303,
+-16396, -16488, -16581, -16673, -16766,
+-16858, -16949, -17041, -17133, -17224,
+-17315, -17406, -17497, -17587, -17678,
+-17768, -17858, -17948, -18037, -18127,
+-18216, -18305, -18394, -18483, -18571,
+-18659, -18747, -18835, -18923, -19010,
+-19098, -19185, -19271, -19358, -19444,
+-19531, -19617, -19702, -19788, -19873,
+-19959, -20043, -20128, -20213, -20297,
+-20381, -20465, -20549, -20632, -20715,
+-20798, -20881, -20963, -21046, -21128,
+-21210, -21291, -21373, -21454, -21535,
+-21616, -21696, -21776, -21856, -21936,
+-22016, -22095, -22174, -22253, -22331,
+-22410, -22488, -22566, -22643, -22721,
+-22798, -22875, -22951, -23028, -23104,
+-23180, -23256, -23331, -23406, -23481,
+-23556, -23630, -23704, -23778, -23852,
+-23925, -23998, -24071, -24144, -24216,
+-24288, -24360, -24432, -24503, -24574,
+-24645, -24716, -24786, -24856, -24926,
+-24995, -25064, -25133, -25202, -25270,
+-25339, -25406, -25474, -25541, -25608,
+-25675, -25742, -25808, -25874, -25939,
+-26005, -26070, -26135, -26199, -26264,
+-26327, -26391, -26455, -26518, -26581,
+-26643, -26705, -26767, -26829, -26891,
+-26952, -27013, -27073, -27133, -27193,
+-27253, -27312, -27372, -27430, -27489,
+-27547, -27605, -27663, -27720, -27777,
+-27834, -27890, -27946, -28002, -28058,
+-28113, -28168, -28223, -28277, -28331,
+-28385, -28438, -28491, -28544, -28596,
+-28649, -28701, -28752, -28803, -28854,
+-28905, -28955, -29006, -29055, -29105,
+-29154, -29203, -29251, -29299, -29347,
+-29395, -29442, -29489, -29535, -29582,
+-29628, -29673, -29719, -29764, -29808,
+-29853, -29897, -29941, -29984, -30027,
+-30070, -30112, -30154, -30196, -30238,
+-30279, -30320, -30360, -30400, -30440,
+-30480, -30519, -30558, -30596, -30635,
+-30672, -30710, -30747, -30784, -30821,
+-30857, -30893, -30929, -30964, -30999,
+-31033, -31068, -31102, -31135, -31168,
+-31201, -31234, -31266, -31298, -31330,
+-31361, -31392, -31422, -31453, -31483,
+-31512, -31541, -31570, -31599, -31627,
+-31655, -31682, -31710, -31737, -31763,
+-31789, -31815, -31841, -31866, -31891,
+-31915, -31939, -31963, -31986, -32010,
+-32032, -32055, -32077, -32099, -32120,
+-32141, -32162, -32182, -32202, -32222,
+-32241, -32260, -32279, -32297, -32315,
+-32333, -32350, -32367, -32383, -32399,
+-32415, -32431, -32446, -32461, -32475,
+-32489, -32503, -32517, -32530, -32542,
+-32555, -32567, -32579, -32590, -32601,
+-32612, -32622, -32632, -32641, -32651,
+-32659, -32668, -32676, -32684, -32692,
+-32699, -32706, -32712, -32718, -32724,
+-32729, -32734, -32739, -32743, -32747,
+-32751, -32754, -32757, -32760, -32762,
+-32764, -32765, -32767, -32767, -32767,
+32767, 32767, 32765, 32761, 32756,
+32750, 32742, 32732, 32722, 32710,
+32696, 32681, 32665, 32647, 32628,
+32608, 32586, 32562, 32538, 32512,
+32484, 32455, 32425, 32393, 32360,
+32326, 32290, 32253, 32214, 32174,
+32133, 32090, 32046, 32001, 31954,
+31906, 31856, 31805, 31753, 31700,
+31645, 31588, 31530, 31471, 31411,
+31349, 31286, 31222, 31156, 31089,
+31020, 30951, 30880, 30807, 30733,
+30658, 30582, 30504, 30425, 30345,
+30263, 30181, 30096, 30011, 29924,
+29836, 29747, 29656, 29564, 29471,
+29377, 29281, 29184, 29086, 28987,
+28886, 28784, 28681, 28577, 28471,
+28365, 28257, 28147, 28037, 27925,
+27812, 27698, 27583, 27467, 27349,
+27231, 27111, 26990, 26868, 26744,
+26620, 26494, 26367, 26239, 26110,
+25980, 25849, 25717, 25583, 25449,
+25313, 25176, 25038, 24900, 24760,
+24619, 24477, 24333, 24189, 24044,
+23898, 23751, 23602, 23453, 23303,
+23152, 22999, 22846, 22692, 22537,
+22380, 22223, 22065, 21906, 21746,
+21585, 21423, 21261, 21097, 20933,
+20767, 20601, 20434, 20265, 20096,
+19927, 19756, 19584, 19412, 19239,
+19065, 18890, 18714, 18538, 18361,
+18183, 18004, 17824, 17644, 17463,
+17281, 17098, 16915, 16731, 16546,
+16361, 16175, 15988, 15800, 15612,
+15423, 15234, 15043, 14852, 14661,
+14469, 14276, 14083, 13889, 13694,
+13499, 13303, 13107, 12910, 12713,
+12515, 12317, 12118, 11918, 11718,
+11517, 11316, 11115, 10913, 10710,
+10508, 10304, 10100, 9896, 9691,
+9486, 9281, 9075, 8869, 8662,
+8455, 8248, 8040, 7832, 7623,
+7415, 7206, 6996, 6787, 6577,
+6366, 6156, 5945, 5734, 5523,
+5311, 5100, 4888, 4675, 4463,
+4251, 4038, 3825, 3612, 3399,
+3185, 2972, 2758, 2544, 2330,
+2116, 1902, 1688, 1474, 1260,
+1045, 831, 617, 402, 188,
+-27, -241, -456, -670, -885,
+-1099, -1313, -1528, -1742, -1956,
+-2170, -2384, -2598, -2811, -3025,
+-3239, -3452, -3665, -3878, -4091,
+-4304, -4516, -4728, -4941, -5153,
+-5364, -5576, -5787, -5998, -6209,
+-6419, -6629, -6839, -7049, -7258,
+-7467, -7676, -7884, -8092, -8300,
+-8507, -8714, -8920, -9127, -9332,
+-9538, -9743, -9947, -10151, -10355,
+-10558, -10761, -10963, -11165, -11367,
+-11568, -11768, -11968, -12167, -12366,
+-12565, -12762, -12960, -13156, -13352,
+-13548, -13743, -13937, -14131, -14324,
+-14517, -14709, -14900, -15091, -15281,
+-15470, -15659, -15847, -16035, -16221,
+-16407, -16593, -16777, -16961, -17144,
+-17326, -17508, -17689, -17869, -18049,
+-18227, -18405, -18582, -18758, -18934,
+-19108, -19282, -19455, -19627, -19799,
+-19969, -20139, -20308, -20475, -20642,
+-20809, -20974, -21138, -21301, -21464,
+-21626, -21786, -21946, -22105, -22263,
+-22420, -22575, -22730, -22884, -23037,
+-23189, -23340, -23490, -23640, -23788,
+-23935, -24080, -24225, -24369, -24512,
+-24654, -24795, -24934, -25073, -25211,
+-25347, -25482, -25617, -25750, -25882,
+-26013, -26143, -26272, -26399, -26526,
+-26651, -26775, -26898, -27020, -27141,
+-27260, -27379, -27496, -27612, -27727,
+-27841, -27953, -28065, -28175, -28284,
+-28391, -28498, -28603, -28707, -28810,
+-28911, -29012, -29111, -29209, -29305,
+-29401, -29495, -29587, -29679, -29769,
+-29858, -29946, -30032, -30118, -30201,
+-30284, -30365, -30445, -30524, -30601,
+-30677, -30752, -30825, -30897, -30968,
+-31038, -31106, -31172, -31238, -31302,
+-31365, -31426, -31486, -31545, -31602,
+-31658, -31713, -31766, -31818, -31869,
+-31918, -31966, -32012, -32058, -32101,
+-32144, -32185, -32224, -32262, -32299,
+-32335, -32369, -32401, -32433, -32463,
+-32491, -32518, -32544, -32568, -32591,
+-32613, -32633, -32652, -32669, -32685,
+-32700, -32713, -32724, -32735, -32744,
+-32751, -32757, -32762, -32766, -32767,
+32767, 32764, 32755, 32741, 32720,
+32694, 32663, 32626, 32583, 32535,
+32481, 32421, 32356, 32286, 32209,
+32128, 32041, 31948, 31850, 31747,
+31638, 31523, 31403, 31278, 31148,
+31012, 30871, 30724, 30572, 30415,
+30253, 30086, 29913, 29736, 29553,
+29365, 29172, 28974, 28771, 28564,
+28351, 28134, 27911, 27684, 27452,
+27216, 26975, 26729, 26478, 26223,
+25964, 25700, 25432, 25159, 24882,
+24601, 24315, 24026, 23732, 23434,
+23133, 22827, 22517, 22204, 21886,
+21565, 21240, 20912, 20580, 20244,
+19905, 19563, 19217, 18868, 18516,
+18160, 17802, 17440, 17075, 16708,
+16338, 15964, 15588, 15210, 14829,
+14445, 14059, 13670, 13279, 12886,
+12490, 12093, 11693, 11291, 10888,
+10482, 10075, 9666, 9255, 8843,
+8429, 8014, 7597, 7180, 6760,
+6340, 5919, 5496, 5073, 4649,
+4224, 3798, 3372, 2945, 2517,
+2090, 1661, 1233, 804, 375,
+-54, -483, -911, -1340, -1768,
+-2197, -2624, -3052, -3479, -3905,
+-4330, -4755, -5179, -5602, -6024,
+-6445, -6865, -7284, -7702, -8118,
+-8533, -8946, -9358, -9768, -10177,
+-10584, -10989, -11392, -11793, -12192,
+-12589, -12984, -13377, -13767, -14155,
+-14541, -14924, -15305, -15683, -16058,
+-16430, -16800, -17167, -17531, -17892,
+-18249, -18604, -18956, -19304, -19649,
+-19990, -20329, -20663, -20994, -21322,
+-21646, -21966, -22282, -22595, -22904,
+-23208, -23509, -23806, -24099, -24387,
+-24672, -24952, -25228, -25499, -25766,
+-26029, -26288, -26541, -26791, -27035,
+-27275, -27511, -27741, -27967, -28188,
+-28405, -28616, -28823, -29024, -29221,
+-29412, -29599, -29780, -29957, -30128,
+-30294, -30455, -30611, -30761, -30906,
+-31046, -31181, -31310, -31434, -31552,
+-31665, -31773, -31875, -31972, -32063,
+-32149, -32229, -32304, -32373, -32437,
+-32495, -32547, -32594, -32635, -32671,
+-32701, -32726, -32745, -32758, -32766,
+32767, 32754, 32717, 32658, 32577,
+32473, 32348, 32200, 32029, 31837,
+31624, 31388, 31131, 30853, 30553,
+30232, 29891, 29530, 29148, 28746,
+28324, 27883, 27423, 26944, 26447,
+25931, 25398, 24847, 24279, 23695,
+23095, 22478, 21846, 21199, 20538,
+19863, 19174, 18472, 17757, 17030,
+16291, 15541, 14781, 14010, 13230,
+12441, 11643, 10837, 10024, 9204,
+8377, 7545, 6708, 5866, 5020,
+4171, 3319, 2464, 1608, 751,
+-107, -965, -1822, -2678, -3532,
+-4383, -5232, -6077, -6918, -7754,
+-8585, -9409, -10228, -11039, -11843,
+-12639, -13426, -14204, -14972, -15730,
+-16477, -17213, -17937, -18648, -19347,
+-20033, -20705, -21363, -22006, -22634,
+-23246, -23843, -24423, -24986, -25533,
+-26062, -26573, -27066, -27540, -27995,
+-28431, -28848, -29245, -29622, -29979,
+-30315, -30630, -30924, -31197, -31449,
+-31679, -31887, -32074, -32239, -32381,
+-32501, -32600, -32675, -32729, -32759,
+#endif
+};
+#endif
+
+static const CELTMode mode48000_960_120 = {
+48000,    /* Fs */
+120,    /* overlap */
+21,    /* nbEBands */
+21,    /* effEBands */
+{27853, 0, 4096, 8192, },    /* preemph */
+eband5ms,    /* eBands */
+3,    /* maxLM */
+8,    /* nbShortMdcts */
+120,    /* shortMdctSize */
+11,    /* nbAllocVectors */
+band_allocation,    /* allocVectors */
+logN400,    /* logN */
+window120,    /* window */
+{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960},    /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50},    /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50},    /* qext_cache */
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#ifndef DEF_WINDOW240
+#define DEF_WINDOW240
+static const celt_coef window240[240] = {
+#ifdef ENABLE_QEXT
+36124, 325113, 903042, 1769811, 2925272,
+4369225, 6101422, 8121563, 10429297, 13024223,
+15905885, 19073777, 22527339, 26265958, 30288963,
+34595631, 39185180, 44056771, 49209509, 54642435,
+60354533, 66344724, 72611866, 79154752, 85972112,
+93062609, 100424835, 108057317, 115958510, 124126796,
+132560487, 141257817, 150216948, 159435962, 168912864,
+178645581, 188631957, 198869754, 209356654, 220090250,
+231068053, 242287487, 253745886, 265440499, 277368483,
+289526906, 301912744, 314522883, 327354113, 340403136,
+353666556, 367140886, 380822544, 394707853, 408793044,
+423074251, 437547515, 452208783, 467053909, 482078654,
+497278684, 512649576, 528186815, 543885797, 559741828,
+575750127, 591905825, 608203972, 624639532, 641207388,
+657902345, 674719130, 691652394, 708696716, 725846605,
+743096501, 760440782, 777873759, 795389689, 812982769,
+830647145, 848376914, 866166126, 884008788, 901898872,
+919830310, 937797006, 955792839, 973811661, 991847308,
+1009893601, 1027944353, 1045993369, 1064034454, 1082061416,
+1100068075, 1118048258, 1135995815, 1153904614, 1171768555,
+1189581567, 1207337616, 1225030710, 1242654904, 1260204305,
+1277673075, 1295055437, 1312345681, 1329538165, 1346627326,
+1363607677, 1380473817, 1397220435, 1413842311, 1430334323,
+1446691453, 1462908786, 1478981520, 1494904965, 1510674550,
+1526285825, 1541734465, 1557016274, 1572127189, 1587063280,
+1601820758, 1616395971, 1630785416, 1644985731, 1658993707,
+1672806283, 1686420553, 1699833765, 1713043324, 1726046792,
+1738841892, 1751426506, 1763798678, 1775956615, 1787898686,
+1799623424, 1811129525, 1822415848, 1833481417, 1844325418,
+1854947198, 1865346267, 1875522297, 1885475119, 1895204720,
+1904711247, 1913995001, 1923056438, 1931896164, 1940514936,
+1948913657, 1957093375, 1965055281, 1972800706, 1980331118,
+1987648116, 1994753433, 2001648928, 2008336584, 2014818504,
+2021096911, 2027174137, 2033052626, 2038734929, 2044223696,
+2049521676, 2054631712, 2059556735, 2064299763, 2068863893,
+2073252301, 2077468232, 2081515002, 2085395988, 2089114627,
+2092674410, 2096078878, 2099331616, 2102436251, 2105396446,
+2108215896, 2110898322, 2113447469, 2115867100, 2118160991,
+2120332927, 2122386699, 2124326098, 2126154912, 2127876920,
+2129495889, 2131015570, 2132439692, 2133771963, 2135016059,
+2136175624, 2137254268, 2138255559, 2139183022, 2140040133,
+2140830320, 2141556955, 2142223351, 2142832762, 2143388377,
+2143893317, 2144350634, 2144763305, 2145134231, 2145466235,
+2145762059, 2146024357, 2146255701, 2146458570, 2146635355,
+2146788350, 2146919756, 2147031676, 2147126111, 2147204964,
+2147270033, 2147323012, 2147365487, 2147398940, 2147424741,
+2147444152, 2147458322, 2147468290, 2147474980, 2147479203,
+2147481655, 2147482918, 2147483458, 2147483623, 2147483647,
+#else
+1, 5, 14, 27, 45,
+67, 93, 124, 159, 199,
+243, 291, 344, 401, 462,
+528, 598, 672, 751, 834,
+921, 1012, 1108, 1208, 1312,
+1420, 1532, 1649, 1769, 1894,
+2023, 2155, 2292, 2433, 2577,
+2726, 2878, 3035, 3195, 3358,
+3526, 3697, 3872, 4050, 4232,
+4418, 4607, 4799, 4995, 5194,
+5397, 5602, 5811, 6023, 6238,
+6456, 6676, 6900, 7127, 7356,
+7588, 7822, 8059, 8299, 8541,
+8785, 9032, 9280, 9531, 9784,
+10039, 10295, 10554, 10814, 11076,
+11339, 11603, 11869, 12137, 12405,
+12675, 12945, 13217, 13489, 13762,
+14035, 14310, 14584, 14859, 15134,
+15410, 15685, 15961, 16236, 16511,
+16786, 17060, 17334, 17607, 17880,
+18152, 18423, 18692, 18961, 19229,
+19496, 19761, 20025, 20287, 20548,
+20807, 21064, 21320, 21574, 21825,
+22075, 22322, 22567, 22810, 23051,
+23289, 23525, 23758, 23989, 24217,
+24442, 24664, 24884, 25100, 25314,
+25525, 25733, 25937, 26139, 26337,
+26533, 26725, 26913, 27099, 27281,
+27460, 27636, 27808, 27977, 28142,
+28304, 28463, 28618, 28770, 28919,
+29064, 29205, 29344, 29478, 29610,
+29738, 29863, 29984, 30103, 30217,
+30329, 30438, 30543, 30645, 30744,
+30839, 30932, 31022, 31109, 31192,
+31273, 31351, 31426, 31499, 31568,
+31635, 31700, 31761, 31821, 31877,
+31932, 31984, 32033, 32081, 32126,
+32169, 32210, 32249, 32286, 32321,
+32354, 32385, 32415, 32443, 32469,
+32494, 32517, 32538, 32559, 32578,
+32595, 32612, 32627, 32641, 32654,
+32666, 32678, 32688, 32697, 32706,
+32713, 32720, 32726, 32732, 32737,
+32742, 32746, 32749, 32752, 32755,
+32757, 32759, 32761, 32763, 32764,
+32765, 32766, 32766, 32767, 32767,
+32767, 32767, 32767, 32767, 32767,
+32767, 32767, 32767, 32767, 32767,
+#endif
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES96000_1920
+#define FFT_TWIDDLES96000_1920
+static const kiss_twiddle_cpx fft_twiddles96000_1920[960] = {
+#ifdef ENABLE_QEXT
+{2147483647, 0}, {2147437652, -14055147},
+{2147299668, -28109692}, {2147069700, -42163034},
+{2146747759, -56214568}, {2146333858, -70263695},
+{2145828016, -84309812}, {2145230253, -98352318},
+{2144540596, -112390610}, {2143759074, -126424088},
+{2142885721, -140452151}, {2141920573, -154474196},
+{2140863673, -168489625}, {2139715065, -182497836},
+{2138474799, -196498230}, {2137142927, -210490206},
+{2135719508, -224473166}, {2134204601, -238446509},
+{2132598273, -252409639}, {2130900591, -266361956},
+{2129111628, -280302863}, {2127231461, -294231763},
+{2125260170, -308148059}, {2123197841, -322051155},
+{2121044561, -335940456}, {2118800422, -349815365},
+{2116465521, -363675290}, {2114039958, -377519637},
+{2111523836, -391347811}, {2108917263, -405159222},
+{2106220352, -418953276}, {2103433217, -432729385},
+{2100555978, -446486956}, {2097588758, -460225402},
+{2094531684, -473944133}, {2091384888, -487642562},
+{2088148504, -501320102}, {2084822670, -514976167},
+{2081407530, -528610172}, {2077903229, -542221533},
+{2074309917, -555809667}, {2070627749, -569373992},
+{2066856882, -582913927}, {2062997478, -596428893},
+{2059049702, -609918309}, {2055013723, -623381598},
+{2050889714, -636818183}, {2046677852, -650227490},
+{2042378317, -663608942}, {2037991293, -676961968},
+{2033516969, -690285996}, {2028955535, -703580453},
+{2024307188, -716844772}, {2019572126, -730078383},
+{2014750553, -743280720}, {2009842674, -756451218},
+{2004848700, -769589312}, {1999768845, -782694439},
+{1994603327, -795766038}, {1989352366, -808803549},
+{1984016189, -821806413}, {1978595022, -834774075},
+{1973089100, -847705977}, {1967498656, -860601566},
+{1961823932, -873460290}, {1956065170, -886281598},
+{1950222616, -899064940}, {1944296521, -911809770},
+{1938287139, -924515541}, {1932194727, -937181708},
+{1926019547, -949807730}, {1919761862, -962393065},
+{1913421941, -974937175}, {1907000055, -987439521},
+{1900496480, -999899569}, {1893911494, -1012316784},
+{1887245379, -1024690635}, {1880498421, -1037020592},
+{1873670908, -1049306126}, {1866763134, -1061546712},
+{1859775393, -1073741824}, {1852707986, -1085890941},
+{1845561216, -1097993542}, {1838335387, -1110049108},
+{1831030811, -1122057124}, {1823647799, -1134017074},
+{1816186668, -1145928447}, {1808647737, -1157790732},
+{1801031331, -1169603422}, {1793337774, -1181366009},
+{1785567396, -1193077991}, {1777720531, -1204738865},
+{1769797514, -1216348132}, {1761798685, -1227905295},
+{1753724386, -1239409858}, {1745574963, -1250861329},
+{1737350766, -1262259218}, {1729052147, -1273603035},
+{1720679461, -1284892296}, {1712233066, -1296126516},
+{1703713325, -1307305214}, {1695120603, -1318427912},
+{1686455268, -1329494133}, {1677717690, -1340503402},
+{1668908244, -1351455249}, {1660027308, -1362349204},
+{1651075262, -1373184801}, {1642052490, -1383961574},
+{1632959377, -1394679064}, {1623796314, -1405336810},
+{1614563692, -1415934356}, {1605261909, -1426471249},
+{1595891361, -1436947036}, {1586452450, -1447361268},
+{1576945581, -1457713501}, {1567371161, -1468003290},
+{1557729600, -1478230195}, {1548021312, -1488393778},
+{1538246711, -1498493602}, {1528406216, -1508529236},
+{1518500250, -1518500250}, {1508529236, -1528406216},
+{1498493602, -1538246711}, {1488393778, -1548021312},
+{1478230195, -1557729600}, {1468003290, -1567371161},
+{1457713501, -1576945581}, {1447361268, -1586452450},
+{1436947036, -1595891361}, {1426471249, -1605261909},
+{1415934356, -1614563692}, {1405336810, -1623796314},
+{1394679064, -1632959377}, {1383961574, -1642052490},
+{1373184801, -1651075262}, {1362349204, -1660027308},
+{1351455249, -1668908244}, {1340503402, -1677717690},
+{1329494133, -1686455268}, {1318427912, -1695120603},
+{1307305214, -1703713325}, {1296126516, -1712233066},
+{1284892296, -1720679461}, {1273603035, -1729052147},
+{1262259218, -1737350766}, {1250861329, -1745574963},
+{1239409858, -1753724386}, {1227905295, -1761798685},
+{1216348132, -1769797514}, {1204738865, -1777720531},
+{1193077991, -1785567396}, {1181366009, -1793337774},
+{1169603422, -1801031331}, {1157790732, -1808647737},
+{1145928447, -1816186668}, {1134017074, -1823647799},
+{1122057124, -1831030811}, {1110049108, -1838335387},
+{1097993542, -1845561216}, {1085890941, -1852707986},
+{1073741824, -1859775393}, {1061546712, -1866763134},
+{1049306126, -1873670908}, {1037020592, -1880498421},
+{1024690635, -1887245379}, {1012316784, -1893911494},
+{999899569, -1900496480}, {987439521, -1907000055},
+{974937175, -1913421941}, {962393065, -1919761862},
+{949807730, -1926019547}, {937181708, -1932194727},
+{924515541, -1938287139}, {911809770, -1944296521},
+{899064940, -1950222616}, {886281598, -1956065170},
+{873460290, -1961823932}, {860601566, -1967498656},
+{847705977, -1973089100}, {834774075, -1978595022},
+{821806413, -1984016189}, {808803549, -1989352366},
+{795766038, -1994603327}, {782694439, -1999768845},
+{769589312, -2004848700}, {756451218, -2009842674},
+{743280720, -2014750553}, {730078383, -2019572126},
+{716844772, -2024307188}, {703580453, -2028955535},
+{690285996, -2033516969}, {676961968, -2037991293},
+{663608942, -2042378317}, {650227490, -2046677852},
+{636818183, -2050889714}, {623381598, -2055013723},
+{609918309, -2059049702}, {596428893, -2062997478},
+{582913927, -2066856882}, {569373992, -2070627749},
+{555809667, -2074309917}, {542221533, -2077903229},
+{528610172, -2081407530}, {514976167, -2084822670},
+{501320102, -2088148504}, {487642562, -2091384888},
+{473944133, -2094531684}, {460225402, -2097588758},
+{446486956, -2100555978}, {432729385, -2103433217},
+{418953276, -2106220352}, {405159222, -2108917263},
+{391347811, -2111523836}, {377519637, -2114039958},
+{363675290, -2116465521}, {349815365, -2118800422},
+{335940456, -2121044561}, {322051155, -2123197841},
+{308148059, -2125260170}, {294231763, -2127231461},
+{280302863, -2129111628}, {266361956, -2130900591},
+{252409639, -2132598273}, {238446509, -2134204601},
+{224473166, -2135719508}, {210490206, -2137142927},
+{196498230, -2138474799}, {182497836, -2139715065},
+{168489625, -2140863673}, {154474196, -2141920573},
+{140452151, -2142885721}, {126424088, -2143759074},
+{112390610, -2144540596}, {98352318, -2145230253},
+{84309812, -2145828016}, {70263695, -2146333858},
+{56214568, -2146747759}, {42163034, -2147069700},
+{28109692, -2147299668}, {14055147, -2147437652},
+{0, -2147483648}, {-14055147, -2147437652},
+{-28109692, -2147299668}, {-42163034, -2147069700},
+{-56214568, -2146747759}, {-70263695, -2146333858},
+{-84309812, -2145828016}, {-98352318, -2145230253},
+{-112390610, -2144540596}, {-126424088, -2143759074},
+{-140452151, -2142885721}, {-154474196, -2141920573},
+{-168489625, -2140863673}, {-182497836, -2139715065},
+{-196498230, -2138474799}, {-210490206, -2137142927},
+{-224473166, -2135719508}, {-238446509, -2134204601},
+{-252409639, -2132598273}, {-266361956, -2130900591},
+{-280302863, -2129111628}, {-294231763, -2127231461},
+{-308148059, -2125260170}, {-322051155, -2123197841},
+{-335940456, -2121044561}, {-349815365, -2118800422},
+{-363675290, -2116465521}, {-377519637, -2114039958},
+{-391347811, -2111523836}, {-405159222, -2108917263},
+{-418953276, -2106220352}, {-432729385, -2103433217},
+{-446486956, -2100555978}, {-460225402, -2097588758},
+{-473944133, -2094531684}, {-487642562, -2091384888},
+{-501320102, -2088148504}, {-514976167, -2084822670},
+{-528610172, -2081407530}, {-542221533, -2077903229},
+{-555809667, -2074309917}, {-569373992, -2070627749},
+{-582913927, -2066856882}, {-596428893, -2062997478},
+{-609918309, -2059049702}, {-623381598, -2055013723},
+{-636818183, -2050889714}, {-650227490, -2046677852},
+{-663608942, -2042378317}, {-676961968, -2037991293},
+{-690285996, -2033516969}, {-703580453, -2028955535},
+{-716844772, -2024307188}, {-730078383, -2019572126},
+{-743280720, -2014750553}, {-756451218, -2009842674},
+{-769589312, -2004848700}, {-782694439, -1999768845},
+{-795766038, -1994603327}, {-808803549, -1989352366},
+{-821806413, -1984016189}, {-834774075, -1978595022},
+{-847705977, -1973089100}, {-860601566, -1967498656},
+{-873460290, -1961823932}, {-886281598, -1956065170},
+{-899064940, -1950222616}, {-911809770, -1944296521},
+{-924515541, -1938287139}, {-937181708, -1932194727},
+{-949807730, -1926019547}, {-962393065, -1919761862},
+{-974937175, -1913421941}, {-987439521, -1907000055},
+{-999899569, -1900496480}, {-1012316784, -1893911494},
+{-1024690635, -1887245379}, {-1037020592, -1880498421},
+{-1049306126, -1873670908}, {-1061546712, -1866763134},
+{-1073741824, -1859775393}, {-1085890941, -1852707986},
+{-1097993542, -1845561216}, {-1110049108, -1838335387},
+{-1122057124, -1831030811}, {-1134017074, -1823647799},
+{-1145928447, -1816186668}, {-1157790732, -1808647737},
+{-1169603422, -1801031331}, {-1181366009, -1793337774},
+{-1193077991, -1785567396}, {-1204738865, -1777720531},
+{-1216348132, -1769797514}, {-1227905295, -1761798685},
+{-1239409858, -1753724386}, {-1250861329, -1745574963},
+{-1262259218, -1737350766}, {-1273603035, -1729052147},
+{-1284892296, -1720679461}, {-1296126516, -1712233066},
+{-1307305214, -1703713325}, {-1318427912, -1695120603},
+{-1329494133, -1686455268}, {-1340503402, -1677717690},
+{-1351455249, -1668908244}, {-1362349204, -1660027308},
+{-1373184801, -1651075262}, {-1383961574, -1642052490},
+{-1394679064, -1632959377}, {-1405336810, -1623796314},
+{-1415934356, -1614563692}, {-1426471249, -1605261909},
+{-1436947036, -1595891361}, {-1447361268, -1586452450},
+{-1457713501, -1576945581}, {-1468003290, -1567371161},
+{-1478230195, -1557729600}, {-1488393778, -1548021312},
+{-1498493602, -1538246711}, {-1508529236, -1528406216},
+{-1518500250, -1518500250}, {-1528406216, -1508529236},
+{-1538246711, -1498493602}, {-1548021312, -1488393778},
+{-1557729600, -1478230195}, {-1567371161, -1468003290},
+{-1576945581, -1457713501}, {-1586452450, -1447361268},
+{-1595891361, -1436947036}, {-1605261909, -1426471249},
+{-1614563692, -1415934356}, {-1623796314, -1405336810},
+{-1632959377, -1394679064}, {-1642052490, -1383961574},
+{-1651075262, -1373184801}, {-1660027308, -1362349204},
+{-1668908244, -1351455249}, {-1677717690, -1340503402},
+{-1686455268, -1329494133}, {-1695120603, -1318427912},
+{-1703713325, -1307305214}, {-1712233066, -1296126516},
+{-1720679461, -1284892296}, {-1729052147, -1273603035},
+{-1737350766, -1262259218}, {-1745574963, -1250861329},
+{-1753724386, -1239409858}, {-1761798685, -1227905295},
+{-1769797514, -1216348132}, {-1777720531, -1204738865},
+{-1785567396, -1193077991}, {-1793337774, -1181366009},
+{-1801031331, -1169603422}, {-1808647737, -1157790732},
+{-1816186668, -1145928447}, {-1823647799, -1134017074},
+{-1831030811, -1122057124}, {-1838335387, -1110049108},
+{-1845561216, -1097993542}, {-1852707986, -1085890941},
+{-1859775393, -1073741824}, {-1866763134, -1061546712},
+{-1873670908, -1049306126}, {-1880498421, -1037020592},
+{-1887245379, -1024690635}, {-1893911494, -1012316784},
+{-1900496480, -999899569}, {-1907000055, -987439521},
+{-1913421941, -974937175}, {-1919761862, -962393065},
+{-1926019547, -949807730}, {-1932194727, -937181708},
+{-1938287139, -924515541}, {-1944296521, -911809770},
+{-1950222616, -899064940}, {-1956065170, -886281598},
+{-1961823932, -873460290}, {-1967498656, -860601566},
+{-1973089100, -847705977}, {-1978595022, -834774075},
+{-1984016189, -821806413}, {-1989352366, -808803549},
+{-1994603327, -795766038}, {-1999768845, -782694439},
+{-2004848700, -769589312}, {-2009842674, -756451218},
+{-2014750553, -743280720}, {-2019572126, -730078383},
+{-2024307188, -716844772}, {-2028955535, -703580453},
+{-2033516969, -690285996}, {-2037991293, -676961968},
+{-2042378317, -663608942}, {-2046677852, -650227490},
+{-2050889714, -636818183}, {-2055013723, -623381598},
+{-2059049702, -609918309}, {-2062997478, -596428893},
+{-2066856882, -582913927}, {-2070627749, -569373992},
+{-2074309917, -555809667}, {-2077903229, -542221533},
+{-2081407530, -528610172}, {-2084822670, -514976167},
+{-2088148504, -501320102}, {-2091384888, -487642562},
+{-2094531684, -473944133}, {-2097588758, -460225402},
+{-2100555978, -446486956}, {-2103433217, -432729385},
+{-2106220352, -418953276}, {-2108917263, -405159222},
+{-2111523836, -391347811}, {-2114039958, -377519637},
+{-2116465521, -363675290}, {-2118800422, -349815365},
+{-2121044561, -335940456}, {-2123197841, -322051155},
+{-2125260170, -308148059}, {-2127231461, -294231763},
+{-2129111628, -280302863}, {-2130900591, -266361956},
+{-2132598273, -252409639}, {-2134204601, -238446509},
+{-2135719508, -224473166}, {-2137142927, -210490206},
+{-2138474799, -196498230}, {-2139715065, -182497836},
+{-2140863673, -168489625}, {-2141920573, -154474196},
+{-2142885721, -140452151}, {-2143759074, -126424088},
+{-2144540596, -112390610}, {-2145230253, -98352318},
+{-2145828016, -84309812}, {-2146333858, -70263695},
+{-2146747759, -56214568}, {-2147069700, -42163034},
+{-2147299668, -28109692}, {-2147437652, -14055147},
+{-2147483648, 0}, {-2147437652, 14055147},
+{-2147299668, 28109692}, {-2147069700, 42163034},
+{-2146747759, 56214568}, {-2146333858, 70263695},
+{-2145828016, 84309812}, {-2145230253, 98352318},
+{-2144540596, 112390610}, {-2143759074, 126424088},
+{-2142885721, 140452151}, {-2141920573, 154474196},
+{-2140863673, 168489625}, {-2139715065, 182497836},
+{-2138474799, 196498230}, {-2137142927, 210490206},
+{-2135719508, 224473166}, {-2134204601, 238446509},
+{-2132598273, 252409639}, {-2130900591, 266361956},
+{-2129111628, 280302863}, {-2127231461, 294231763},
+{-2125260170, 308148059}, {-2123197841, 322051155},
+{-2121044561, 335940456}, {-2118800422, 349815365},
+{-2116465521, 363675290}, {-2114039958, 377519637},
+{-2111523836, 391347811}, {-2108917263, 405159222},
+{-2106220352, 418953276}, {-2103433217, 432729385},
+{-2100555978, 446486956}, {-2097588758, 460225402},
+{-2094531684, 473944133}, {-2091384888, 487642562},
+{-2088148504, 501320102}, {-2084822670, 514976167},
+{-2081407530, 528610172}, {-2077903229, 542221533},
+{-2074309917, 555809667}, {-2070627749, 569373992},
+{-2066856882, 582913927}, {-2062997478, 596428893},
+{-2059049702, 609918309}, {-2055013723, 623381598},
+{-2050889714, 636818183}, {-2046677852, 650227490},
+{-2042378317, 663608942}, {-2037991293, 676961968},
+{-2033516969, 690285996}, {-2028955535, 703580453},
+{-2024307188, 716844772}, {-2019572126, 730078383},
+{-2014750553, 743280720}, {-2009842674, 756451218},
+{-2004848700, 769589312}, {-1999768845, 782694439},
+{-1994603327, 795766038}, {-1989352366, 808803549},
+{-1984016189, 821806413}, {-1978595022, 834774075},
+{-1973089100, 847705977}, {-1967498656, 860601566},
+{-1961823932, 873460290}, {-1956065170, 886281598},
+{-1950222616, 899064940}, {-1944296521, 911809770},
+{-1938287139, 924515541}, {-1932194727, 937181708},
+{-1926019547, 949807730}, {-1919761862, 962393065},
+{-1913421941, 974937175}, {-1907000055, 987439521},
+{-1900496480, 999899569}, {-1893911494, 1012316784},
+{-1887245379, 1024690635}, {-1880498421, 1037020592},
+{-1873670908, 1049306126}, {-1866763134, 1061546712},
+{-1859775393, 1073741824}, {-1852707986, 1085890941},
+{-1845561216, 1097993542}, {-1838335387, 1110049108},
+{-1831030811, 1122057124}, {-1823647799, 1134017074},
+{-1816186668, 1145928447}, {-1808647737, 1157790732},
+{-1801031331, 1169603422}, {-1793337774, 1181366009},
+{-1785567396, 1193077991}, {-1777720531, 1204738865},
+{-1769797514, 1216348132}, {-1761798685, 1227905295},
+{-1753724386, 1239409858}, {-1745574963, 1250861329},
+{-1737350766, 1262259218}, {-1729052147, 1273603035},
+{-1720679461, 1284892296}, {-1712233066, 1296126516},
+{-1703713325, 1307305214}, {-1695120603, 1318427912},
+{-1686455268, 1329494133}, {-1677717690, 1340503402},
+{-1668908244, 1351455249}, {-1660027308, 1362349204},
+{-1651075262, 1373184801}, {-1642052490, 1383961574},
+{-1632959377, 1394679064}, {-1623796314, 1405336810},
+{-1614563692, 1415934356}, {-1605261909, 1426471249},
+{-1595891361, 1436947036}, {-1586452450, 1447361268},
+{-1576945581, 1457713501}, {-1567371161, 1468003290},
+{-1557729600, 1478230195}, {-1548021312, 1488393778},
+{-1538246711, 1498493602}, {-1528406216, 1508529236},
+{-1518500250, 1518500250}, {-1508529236, 1528406216},
+{-1498493602, 1538246711}, {-1488393778, 1548021312},
+{-1478230195, 1557729600}, {-1468003290, 1567371161},
+{-1457713501, 1576945581}, {-1447361268, 1586452450},
+{-1436947036, 1595891361}, {-1426471249, 1605261909},
+{-1415934356, 1614563692}, {-1405336810, 1623796314},
+{-1394679064, 1632959377}, {-1383961574, 1642052490},
+{-1373184801, 1651075262}, {-1362349204, 1660027308},
+{-1351455249, 1668908244}, {-1340503402, 1677717690},
+{-1329494133, 1686455268}, {-1318427912, 1695120603},
+{-1307305214, 1703713325}, {-1296126516, 1712233066},
+{-1284892296, 1720679461}, {-1273603035, 1729052147},
+{-1262259218, 1737350766}, {-1250861329, 1745574963},
+{-1239409858, 1753724386}, {-1227905295, 1761798685},
+{-1216348132, 1769797514}, {-1204738865, 1777720531},
+{-1193077991, 1785567396}, {-1181366009, 1793337774},
+{-1169603422, 1801031331}, {-1157790732, 1808647737},
+{-1145928447, 1816186668}, {-1134017074, 1823647799},
+{-1122057124, 1831030811}, {-1110049108, 1838335387},
+{-1097993542, 1845561216}, {-1085890941, 1852707986},
+{-1073741824, 1859775393}, {-1061546712, 1866763134},
+{-1049306126, 1873670908}, {-1037020592, 1880498421},
+{-1024690635, 1887245379}, {-1012316784, 1893911494},
+{-999899569, 1900496480}, {-987439521, 1907000055},
+{-974937175, 1913421941}, {-962393065, 1919761862},
+{-949807730, 1926019547}, {-937181708, 1932194727},
+{-924515541, 1938287139}, {-911809770, 1944296521},
+{-899064940, 1950222616}, {-886281598, 1956065170},
+{-873460290, 1961823932}, {-860601566, 1967498656},
+{-847705977, 1973089100}, {-834774075, 1978595022},
+{-821806413, 1984016189}, {-808803549, 1989352366},
+{-795766038, 1994603327}, {-782694439, 1999768845},
+{-769589312, 2004848700}, {-756451218, 2009842674},
+{-743280720, 2014750553}, {-730078383, 2019572126},
+{-716844772, 2024307188}, {-703580453, 2028955535},
+{-690285996, 2033516969}, {-676961968, 2037991293},
+{-663608942, 2042378317}, {-650227490, 2046677852},
+{-636818183, 2050889714}, {-623381598, 2055013723},
+{-609918309, 2059049702}, {-596428893, 2062997478},
+{-582913927, 2066856882}, {-569373992, 2070627749},
+{-555809667, 2074309917}, {-542221533, 2077903229},
+{-528610172, 2081407530}, {-514976167, 2084822670},
+{-501320102, 2088148504}, {-487642562, 2091384888},
+{-473944133, 2094531684}, {-460225402, 2097588758},
+{-446486956, 2100555978}, {-432729385, 2103433217},
+{-418953276, 2106220352}, {-405159222, 2108917263},
+{-391347811, 2111523836}, {-377519637, 2114039958},
+{-363675290, 2116465521}, {-349815365, 2118800422},
+{-335940456, 2121044561}, {-322051155, 2123197841},
+{-308148059, 2125260170}, {-294231763, 2127231461},
+{-280302863, 2129111628}, {-266361956, 2130900591},
+{-252409639, 2132598273}, {-238446509, 2134204601},
+{-224473166, 2135719508}, {-210490206, 2137142927},
+{-196498230, 2138474799}, {-182497836, 2139715065},
+{-168489625, 2140863673}, {-154474196, 2141920573},
+{-140452151, 2142885721}, {-126424088, 2143759074},
+{-112390610, 2144540596}, {-98352318, 2145230253},
+{-84309812, 2145828016}, {-70263695, 2146333858},
+{-56214568, 2146747759}, {-42163034, 2147069700},
+{-28109692, 2147299668}, {-14055147, 2147437652},
+{0, 2147483647}, {14055147, 2147437652},
+{28109692, 2147299668}, {42163034, 2147069700},
+{56214568, 2146747759}, {70263695, 2146333858},
+{84309812, 2145828016}, {98352318, 2145230253},
+{112390610, 2144540596}, {126424088, 2143759074},
+{140452151, 2142885721}, {154474196, 2141920573},
+{168489625, 2140863673}, {182497836, 2139715065},
+{196498230, 2138474799}, {210490206, 2137142927},
+{224473166, 2135719508}, {238446509, 2134204601},
+{252409639, 2132598273}, {266361956, 2130900591},
+{280302863, 2129111628}, {294231763, 2127231461},
+{308148059, 2125260170}, {322051155, 2123197841},
+{335940456, 2121044561}, {349815365, 2118800422},
+{363675290, 2116465521}, {377519637, 2114039958},
+{391347811, 2111523836}, {405159222, 2108917263},
+{418953276, 2106220352}, {432729385, 2103433217},
+{446486956, 2100555978}, {460225402, 2097588758},
+{473944133, 2094531684}, {487642562, 2091384888},
+{501320102, 2088148504}, {514976167, 2084822670},
+{528610172, 2081407530}, {542221533, 2077903229},
+{555809667, 2074309917}, {569373992, 2070627749},
+{582913927, 2066856882}, {596428893, 2062997478},
+{609918309, 2059049702}, {623381598, 2055013723},
+{636818183, 2050889714}, {650227490, 2046677852},
+{663608942, 2042378317}, {676961968, 2037991293},
+{690285996, 2033516969}, {703580453, 2028955535},
+{716844772, 2024307188}, {730078383, 2019572126},
+{743280720, 2014750553}, {756451218, 2009842674},
+{769589312, 2004848700}, {782694439, 1999768845},
+{795766038, 1994603327}, {808803549, 1989352366},
+{821806413, 1984016189}, {834774075, 1978595022},
+{847705977, 1973089100}, {860601566, 1967498656},
+{873460290, 1961823932}, {886281598, 1956065170},
+{899064940, 1950222616}, {911809770, 1944296521},
+{924515541, 1938287139}, {937181708, 1932194727},
+{949807730, 1926019547}, {962393065, 1919761862},
+{974937175, 1913421941}, {987439521, 1907000055},
+{999899569, 1900496480}, {1012316784, 1893911494},
+{1024690635, 1887245379}, {1037020592, 1880498421},
+{1049306126, 1873670908}, {1061546712, 1866763134},
+{1073741824, 1859775393}, {1085890941, 1852707986},
+{1097993542, 1845561216}, {1110049108, 1838335387},
+{1122057124, 1831030811}, {1134017074, 1823647799},
+{1145928447, 1816186668}, {1157790732, 1808647737},
+{1169603422, 1801031331}, {1181366009, 1793337774},
+{1193077991, 1785567396}, {1204738865, 1777720531},
+{1216348132, 1769797514}, {1227905295, 1761798685},
+{1239409858, 1753724386}, {1250861329, 1745574963},
+{1262259218, 1737350766}, {1273603035, 1729052147},
+{1284892296, 1720679461}, {1296126516, 1712233066},
+{1307305214, 1703713325}, {1318427912, 1695120603},
+{1329494133, 1686455268}, {1340503402, 1677717690},
+{1351455249, 1668908244}, {1362349204, 1660027308},
+{1373184801, 1651075262}, {1383961574, 1642052490},
+{1394679064, 1632959377}, {1405336810, 1623796314},
+{1415934356, 1614563692}, {1426471249, 1605261909},
+{1436947036, 1595891361}, {1447361268, 1586452450},
+{1457713501, 1576945581}, {1468003290, 1567371161},
+{1478230195, 1557729600}, {1488393778, 1548021312},
+{1498493602, 1538246711}, {1508529236, 1528406216},
+{1518500250, 1518500250}, {1528406216, 1508529236},
+{1538246711, 1498493602}, {1548021312, 1488393778},
+{1557729600, 1478230195}, {1567371161, 1468003290},
+{1576945581, 1457713501}, {1586452450, 1447361268},
+{1595891361, 1436947036}, {1605261909, 1426471249},
+{1614563692, 1415934356}, {1623796314, 1405336810},
+{1632959377, 1394679064}, {1642052490, 1383961574},
+{1651075262, 1373184801}, {1660027308, 1362349204},
+{1668908244, 1351455249}, {1677717690, 1340503402},
+{1686455268, 1329494133}, {1695120603, 1318427912},
+{1703713325, 1307305214}, {1712233066, 1296126516},
+{1720679461, 1284892296}, {1729052147, 1273603035},
+{1737350766, 1262259218}, {1745574963, 1250861329},
+{1753724386, 1239409858}, {1761798685, 1227905295},
+{1769797514, 1216348132}, {1777720531, 1204738865},
+{1785567396, 1193077991}, {1793337774, 1181366009},
+{1801031331, 1169603422}, {1808647737, 1157790732},
+{1816186668, 1145928447}, {1823647799, 1134017074},
+{1831030811, 1122057124}, {1838335387, 1110049108},
+{1845561216, 1097993542}, {1852707986, 1085890941},
+{1859775393, 1073741824}, {1866763134, 1061546712},
+{1873670908, 1049306126}, {1880498421, 1037020592},
+{1887245379, 1024690635}, {1893911494, 1012316784},
+{1900496480, 999899569}, {1907000055, 987439521},
+{1913421941, 974937175}, {1919761862, 962393065},
+{1926019547, 949807730}, {1932194727, 937181708},
+{1938287139, 924515541}, {1944296521, 911809770},
+{1950222616, 899064940}, {1956065170, 886281598},
+{1961823932, 873460290}, {1967498656, 860601566},
+{1973089100, 847705977}, {1978595022, 834774075},
+{1984016189, 821806413}, {1989352366, 808803549},
+{1994603327, 795766038}, {1999768845, 782694439},
+{2004848700, 769589312}, {2009842674, 756451218},
+{2014750553, 743280720}, {2019572126, 730078383},
+{2024307188, 716844772}, {2028955535, 703580453},
+{2033516969, 690285996}, {2037991293, 676961968},
+{2042378317, 663608942}, {2046677852, 650227490},
+{2050889714, 636818183}, {2055013723, 623381598},
+{2059049702, 609918309}, {2062997478, 596428893},
+{2066856882, 582913927}, {2070627749, 569373992},
+{2074309917, 555809667}, {2077903229, 542221533},
+{2081407530, 528610172}, {2084822670, 514976167},
+{2088148504, 501320102}, {2091384888, 487642562},
+{2094531684, 473944133}, {2097588758, 460225402},
+{2100555978, 446486956}, {2103433217, 432729385},
+{2106220352, 418953276}, {2108917263, 405159222},
+{2111523836, 391347811}, {2114039958, 377519637},
+{2116465521, 363675290}, {2118800422, 349815365},
+{2121044561, 335940456}, {2123197841, 322051155},
+{2125260170, 308148059}, {2127231461, 294231763},
+{2129111628, 280302863}, {2130900591, 266361956},
+{2132598273, 252409639}, {2134204601, 238446509},
+{2135719508, 224473166}, {2137142927, 210490206},
+{2138474799, 196498230}, {2139715065, 182497836},
+{2140863673, 168489625}, {2141920573, 154474196},
+{2142885721, 140452151}, {2143759074, 126424088},
+{2144540596, 112390610}, {2145230253, 98352318},
+{2145828016, 84309812}, {2146333858, 70263695},
+{2146747759, 56214568}, {2147069700, 42163034},
+{2147299668, 28109692}, {2147437652, 14055147},
+#else
+{32767, 0}, {32767, -214},
+{32765, -429}, {32762, -643},
+{32757, -858}, {32750, -1072},
+{32743, -1286}, {32734, -1501},
+{32723, -1715}, {32711, -1929},
+{32698, -2143}, {32683, -2357},
+{32667, -2571}, {32649, -2785},
+{32631, -2998}, {32610, -3212},
+{32588, -3425}, {32565, -3638},
+{32541, -3851}, {32515, -4064},
+{32488, -4277}, {32459, -4490},
+{32429, -4702}, {32397, -4914},
+{32365, -5126}, {32330, -5338},
+{32295, -5549}, {32258, -5760},
+{32219, -5971}, {32180, -6182},
+{32138, -6393}, {32096, -6603},
+{32052, -6813}, {32007, -7022},
+{31960, -7232}, {31912, -7441},
+{31863, -7650}, {31812, -7858},
+{31760, -8066}, {31706, -8274},
+{31651, -8481}, {31595, -8688},
+{31538, -8895}, {31479, -9101},
+{31419, -9307}, {31357, -9512},
+{31294, -9717}, {31230, -9922},
+{31164, -10126}, {31097, -10330},
+{31029, -10533}, {30959, -10736},
+{30888, -10938}, {30816, -11140},
+{30743, -11342}, {30668, -11543},
+{30592, -11743}, {30514, -11943},
+{30435, -12142}, {30355, -12341},
+{30274, -12540}, {30191, -12738},
+{30107, -12935}, {30022, -13132},
+{29935, -13328}, {29847, -13524},
+{29758, -13719}, {29668, -13913},
+{29576, -14107}, {29483, -14300},
+{29389, -14493}, {29293, -14685},
+{29197, -14876}, {29099, -15067},
+{28999, -15257}, {28899, -15447},
+{28797, -15636}, {28694, -15824},
+{28590, -16011}, {28485, -16198},
+{28378, -16384}, {28270, -16569},
+{28161, -16754}, {28051, -16938},
+{27939, -17121}, {27827, -17304},
+{27713, -17485}, {27598, -17666},
+{27482, -17847}, {27364, -18026},
+{27246, -18205}, {27126, -18383},
+{27005, -18560}, {26883, -18736},
+{26760, -18912}, {26635, -19087},
+{26510, -19261}, {26383, -19434},
+{26255, -19606}, {26127, -19777},
+{25997, -19948}, {25865, -20118},
+{25733, -20286}, {25600, -20454},
+{25466, -20622}, {25330, -20788},
+{25193, -20953}, {25056, -21118},
+{24917, -21281}, {24777, -21444},
+{24636, -21605}, {24494, -21766},
+{24351, -21926}, {24207, -22085},
+{24062, -22243}, {23916, -22400},
+{23769, -22556}, {23621, -22711},
+{23472, -22865}, {23322, -23018},
+{23170, -23170}, {23018, -23322},
+{22865, -23472}, {22711, -23621},
+{22556, -23769}, {22400, -23916},
+{22243, -24062}, {22085, -24207},
+{21926, -24351}, {21766, -24494},
+{21605, -24636}, {21444, -24777},
+{21281, -24917}, {21118, -25056},
+{20953, -25193}, {20788, -25330},
+{20622, -25466}, {20454, -25600},
+{20286, -25733}, {20118, -25865},
+{19948, -25997}, {19777, -26127},
+{19606, -26255}, {19434, -26383},
+{19261, -26510}, {19087, -26635},
+{18912, -26760}, {18736, -26883},
+{18560, -27005}, {18383, -27126},
+{18205, -27246}, {18026, -27364},
+{17847, -27482}, {17666, -27598},
+{17485, -27713}, {17304, -27827},
+{17121, -27939}, {16938, -28051},
+{16754, -28161}, {16569, -28270},
+{16384, -28378}, {16198, -28485},
+{16011, -28590}, {15824, -28694},
+{15636, -28797}, {15447, -28899},
+{15257, -28999}, {15067, -29099},
+{14876, -29197}, {14685, -29293},
+{14493, -29389}, {14300, -29483},
+{14107, -29576}, {13913, -29668},
+{13719, -29758}, {13524, -29847},
+{13328, -29935}, {13132, -30022},
+{12935, -30107}, {12738, -30191},
+{12540, -30274}, {12341, -30355},
+{12142, -30435}, {11943, -30514},
+{11743, -30592}, {11543, -30668},
+{11342, -30743}, {11140, -30816},
+{10938, -30888}, {10736, -30959},
+{10533, -31029}, {10330, -31097},
+{10126, -31164}, {9922, -31230},
+{9717, -31294}, {9512, -31357},
+{9307, -31419}, {9101, -31479},
+{8895, -31538}, {8688, -31595},
+{8481, -31651}, {8274, -31706},
+{8066, -31760}, {7858, -31812},
+{7650, -31863}, {7441, -31912},
+{7232, -31960}, {7022, -32007},
+{6813, -32052}, {6603, -32096},
+{6393, -32138}, {6182, -32180},
+{5971, -32219}, {5760, -32258},
+{5549, -32295}, {5338, -32330},
+{5126, -32365}, {4914, -32397},
+{4702, -32429}, {4490, -32459},
+{4277, -32488}, {4064, -32515},
+{3851, -32541}, {3638, -32565},
+{3425, -32588}, {3212, -32610},
+{2998, -32631}, {2785, -32649},
+{2571, -32667}, {2357, -32683},
+{2143, -32698}, {1929, -32711},
+{1715, -32723}, {1501, -32734},
+{1286, -32743}, {1072, -32750},
+{858, -32757}, {643, -32762},
+{429, -32765}, {214, -32767},
+{0, -32767}, {-214, -32767},
+{-429, -32765}, {-643, -32762},
+{-858, -32757}, {-1072, -32750},
+{-1286, -32743}, {-1501, -32734},
+{-1715, -32723}, {-1929, -32711},
+{-2143, -32698}, {-2357, -32683},
+{-2571, -32667}, {-2785, -32649},
+{-2998, -32631}, {-3212, -32610},
+{-3425, -32588}, {-3638, -32565},
+{-3851, -32541}, {-4064, -32515},
+{-4277, -32488}, {-4490, -32459},
+{-4702, -32429}, {-4914, -32397},
+{-5126, -32365}, {-5338, -32330},
+{-5549, -32295}, {-5760, -32258},
+{-5971, -32219}, {-6182, -32180},
+{-6393, -32138}, {-6603, -32096},
+{-6813, -32052}, {-7022, -32007},
+{-7232, -31960}, {-7441, -31912},
+{-7650, -31863}, {-7858, -31812},
+{-8066, -31760}, {-8274, -31706},
+{-8481, -31651}, {-8688, -31595},
+{-8895, -31538}, {-9101, -31479},
+{-9307, -31419}, {-9512, -31357},
+{-9717, -31294}, {-9922, -31230},
+{-10126, -31164}, {-10330, -31097},
+{-10533, -31029}, {-10736, -30959},
+{-10938, -30888}, {-11140, -30816},
+{-11342, -30743}, {-11543, -30668},
+{-11743, -30592}, {-11943, -30514},
+{-12142, -30435}, {-12341, -30355},
+{-12540, -30274}, {-12738, -30191},
+{-12935, -30107}, {-13132, -30022},
+{-13328, -29935}, {-13524, -29847},
+{-13719, -29758}, {-13913, -29668},
+{-14107, -29576}, {-14300, -29483},
+{-14493, -29389}, {-14685, -29293},
+{-14876, -29197}, {-15067, -29099},
+{-15257, -28999}, {-15447, -28899},
+{-15636, -28797}, {-15824, -28694},
+{-16011, -28590}, {-16198, -28485},
+{-16384, -28378}, {-16569, -28270},
+{-16754, -28161}, {-16938, -28051},
+{-17121, -27939}, {-17304, -27827},
+{-17485, -27713}, {-17666, -27598},
+{-17847, -27482}, {-18026, -27364},
+{-18205, -27246}, {-18383, -27126},
+{-18560, -27005}, {-18736, -26883},
+{-18912, -26760}, {-19087, -26635},
+{-19261, -26510}, {-19434, -26383},
+{-19606, -26255}, {-19777, -26127},
+{-19948, -25997}, {-20118, -25865},
+{-20286, -25733}, {-20454, -25600},
+{-20622, -25466}, {-20788, -25330},
+{-20953, -25193}, {-21118, -25056},
+{-21281, -24917}, {-21444, -24777},
+{-21605, -24636}, {-21766, -24494},
+{-21926, -24351}, {-22085, -24207},
+{-22243, -24062}, {-22400, -23916},
+{-22556, -23769}, {-22711, -23621},
+{-22865, -23472}, {-23018, -23322},
+{-23170, -23170}, {-23322, -23018},
+{-23472, -22865}, {-23621, -22711},
+{-23769, -22556}, {-23916, -22400},
+{-24062, -22243}, {-24207, -22085},
+{-24351, -21926}, {-24494, -21766},
+{-24636, -21605}, {-24777, -21444},
+{-24917, -21281}, {-25056, -21118},
+{-25193, -20953}, {-25330, -20788},
+{-25466, -20622}, {-25600, -20454},
+{-25733, -20286}, {-25865, -20118},
+{-25997, -19948}, {-26127, -19777},
+{-26255, -19606}, {-26383, -19434},
+{-26510, -19261}, {-26635, -19087},
+{-26760, -18912}, {-26883, -18736},
+{-27005, -18560}, {-27126, -18383},
+{-27246, -18205}, {-27364, -18026},
+{-27482, -17847}, {-27598, -17666},
+{-27713, -17485}, {-27827, -17304},
+{-27939, -17121}, {-28051, -16938},
+{-28161, -16754}, {-28270, -16569},
+{-28378, -16384}, {-28485, -16198},
+{-28590, -16011}, {-28694, -15824},
+{-28797, -15636}, {-28899, -15447},
+{-28999, -15257}, {-29099, -15067},
+{-29197, -14876}, {-29293, -14685},
+{-29389, -14493}, {-29483, -14300},
+{-29576, -14107}, {-29668, -13913},
+{-29758, -13719}, {-29847, -13524},
+{-29935, -13328}, {-30022, -13132},
+{-30107, -12935}, {-30191, -12738},
+{-30274, -12540}, {-30355, -12341},
+{-30435, -12142}, {-30514, -11943},
+{-30592, -11743}, {-30668, -11543},
+{-30743, -11342}, {-30816, -11140},
+{-30888, -10938}, {-30959, -10736},
+{-31029, -10533}, {-31097, -10330},
+{-31164, -10126}, {-31230, -9922},
+{-31294, -9717}, {-31357, -9512},
+{-31419, -9307}, {-31479, -9101},
+{-31538, -8895}, {-31595, -8688},
+{-31651, -8481}, {-31706, -8274},
+{-31760, -8066}, {-31812, -7858},
+{-31863, -7650}, {-31912, -7441},
+{-31960, -7232}, {-32007, -7022},
+{-32052, -6813}, {-32096, -6603},
+{-32138, -6393}, {-32180, -6182},
+{-32219, -5971}, {-32258, -5760},
+{-32295, -5549}, {-32330, -5338},
+{-32365, -5126}, {-32397, -4914},
+{-32429, -4702}, {-32459, -4490},
+{-32488, -4277}, {-32515, -4064},
+{-32541, -3851}, {-32565, -3638},
+{-32588, -3425}, {-32610, -3212},
+{-32631, -2998}, {-32649, -2785},
+{-32667, -2571}, {-32683, -2357},
+{-32698, -2143}, {-32711, -1929},
+{-32723, -1715}, {-32734, -1501},
+{-32743, -1286}, {-32750, -1072},
+{-32757, -858}, {-32762, -643},
+{-32765, -429}, {-32767, -214},
+{-32767, 0}, {-32767, 214},
+{-32765, 429}, {-32762, 643},
+{-32757, 858}, {-32750, 1072},
+{-32743, 1286}, {-32734, 1501},
+{-32723, 1715}, {-32711, 1929},
+{-32698, 2143}, {-32683, 2357},
+{-32667, 2571}, {-32649, 2785},
+{-32631, 2998}, {-32610, 3212},
+{-32588, 3425}, {-32565, 3638},
+{-32541, 3851}, {-32515, 4064},
+{-32488, 4277}, {-32459, 4490},
+{-32429, 4702}, {-32397, 4914},
+{-32365, 5126}, {-32330, 5338},
+{-32295, 5549}, {-32258, 5760},
+{-32219, 5971}, {-32180, 6182},
+{-32138, 6393}, {-32096, 6603},
+{-32052, 6813}, {-32007, 7022},
+{-31960, 7232}, {-31912, 7441},
+{-31863, 7650}, {-31812, 7858},
+{-31760, 8066}, {-31706, 8274},
+{-31651, 8481}, {-31595, 8688},
+{-31538, 8895}, {-31479, 9101},
+{-31419, 9307}, {-31357, 9512},
+{-31294, 9717}, {-31230, 9922},
+{-31164, 10126}, {-31097, 10330},
+{-31029, 10533}, {-30959, 10736},
+{-30888, 10938}, {-30816, 11140},
+{-30743, 11342}, {-30668, 11543},
+{-30592, 11743}, {-30514, 11943},
+{-30435, 12142}, {-30355, 12341},
+{-30274, 12540}, {-30191, 12738},
+{-30107, 12935}, {-30022, 13132},
+{-29935, 13328}, {-29847, 13524},
+{-29758, 13719}, {-29668, 13913},
+{-29576, 14107}, {-29483, 14300},
+{-29389, 14493}, {-29293, 14685},
+{-29197, 14876}, {-29099, 15067},
+{-28999, 15257}, {-28899, 15447},
+{-28797, 15636}, {-28694, 15824},
+{-28590, 16011}, {-28485, 16198},
+{-28378, 16384}, {-28270, 16569},
+{-28161, 16754}, {-28051, 16938},
+{-27939, 17121}, {-27827, 17304},
+{-27713, 17485}, {-27598, 17666},
+{-27482, 17847}, {-27364, 18026},
+{-27246, 18205}, {-27126, 18383},
+{-27005, 18560}, {-26883, 18736},
+{-26760, 18912}, {-26635, 19087},
+{-26510, 19261}, {-26383, 19434},
+{-26255, 19606}, {-26127, 19777},
+{-25997, 19948}, {-25865, 20118},
+{-25733, 20286}, {-25600, 20454},
+{-25466, 20622}, {-25330, 20788},
+{-25193, 20953}, {-25056, 21118},
+{-24917, 21281}, {-24777, 21444},
+{-24636, 21605}, {-24494, 21766},
+{-24351, 21926}, {-24207, 22085},
+{-24062, 22243}, {-23916, 22400},
+{-23769, 22556}, {-23621, 22711},
+{-23472, 22865}, {-23322, 23018},
+{-23170, 23170}, {-23018, 23322},
+{-22865, 23472}, {-22711, 23621},
+{-22556, 23769}, {-22400, 23916},
+{-22243, 24062}, {-22085, 24207},
+{-21926, 24351}, {-21766, 24494},
+{-21605, 24636}, {-21444, 24777},
+{-21281, 24917}, {-21118, 25056},
+{-20953, 25193}, {-20788, 25330},
+{-20622, 25466}, {-20454, 25600},
+{-20286, 25733}, {-20118, 25865},
+{-19948, 25997}, {-19777, 26127},
+{-19606, 26255}, {-19434, 26383},
+{-19261, 26510}, {-19087, 26635},
+{-18912, 26760}, {-18736, 26883},
+{-18560, 27005}, {-18383, 27126},
+{-18205, 27246}, {-18026, 27364},
+{-17847, 27482}, {-17666, 27598},
+{-17485, 27713}, {-17304, 27827},
+{-17121, 27939}, {-16938, 28051},
+{-16754, 28161}, {-16569, 28270},
+{-16384, 28378}, {-16198, 28485},
+{-16011, 28590}, {-15824, 28694},
+{-15636, 28797}, {-15447, 28899},
+{-15257, 28999}, {-15067, 29099},
+{-14876, 29197}, {-14685, 29293},
+{-14493, 29389}, {-14300, 29483},
+{-14107, 29576}, {-13913, 29668},
+{-13719, 29758}, {-13524, 29847},
+{-13328, 29935}, {-13132, 30022},
+{-12935, 30107}, {-12738, 30191},
+{-12540, 30274}, {-12341, 30355},
+{-12142, 30435}, {-11943, 30514},
+{-11743, 30592}, {-11543, 30668},
+{-11342, 30743}, {-11140, 30816},
+{-10938, 30888}, {-10736, 30959},
+{-10533, 31029}, {-10330, 31097},
+{-10126, 31164}, {-9922, 31230},
+{-9717, 31294}, {-9512, 31357},
+{-9307, 31419}, {-9101, 31479},
+{-8895, 31538}, {-8688, 31595},
+{-8481, 31651}, {-8274, 31706},
+{-8066, 31760}, {-7858, 31812},
+{-7650, 31863}, {-7441, 31912},
+{-7232, 31960}, {-7022, 32007},
+{-6813, 32052}, {-6603, 32096},
+{-6393, 32138}, {-6182, 32180},
+{-5971, 32219}, {-5760, 32258},
+{-5549, 32295}, {-5338, 32330},
+{-5126, 32365}, {-4914, 32397},
+{-4702, 32429}, {-4490, 32459},
+{-4277, 32488}, {-4064, 32515},
+{-3851, 32541}, {-3638, 32565},
+{-3425, 32588}, {-3212, 32610},
+{-2998, 32631}, {-2785, 32649},
+{-2571, 32667}, {-2357, 32683},
+{-2143, 32698}, {-1929, 32711},
+{-1715, 32723}, {-1501, 32734},
+{-1286, 32743}, {-1072, 32750},
+{-858, 32757}, {-643, 32762},
+{-429, 32765}, {-214, 32767},
+{0, 32767}, {214, 32767},
+{429, 32765}, {643, 32762},
+{858, 32757}, {1072, 32750},
+{1286, 32743}, {1501, 32734},
+{1715, 32723}, {1929, 32711},
+{2143, 32698}, {2357, 32683},
+{2571, 32667}, {2785, 32649},
+{2998, 32631}, {3212, 32610},
+{3425, 32588}, {3638, 32565},
+{3851, 32541}, {4064, 32515},
+{4277, 32488}, {4490, 32459},
+{4702, 32429}, {4914, 32397},
+{5126, 32365}, {5338, 32330},
+{5549, 32295}, {5760, 32258},
+{5971, 32219}, {6182, 32180},
+{6393, 32138}, {6603, 32096},
+{6813, 32052}, {7022, 32007},
+{7232, 31960}, {7441, 31912},
+{7650, 31863}, {7858, 31812},
+{8066, 31760}, {8274, 31706},
+{8481, 31651}, {8688, 31595},
+{8895, 31538}, {9101, 31479},
+{9307, 31419}, {9512, 31357},
+{9717, 31294}, {9922, 31230},
+{10126, 31164}, {10330, 31097},
+{10533, 31029}, {10736, 30959},
+{10938, 30888}, {11140, 30816},
+{11342, 30743}, {11543, 30668},
+{11743, 30592}, {11943, 30514},
+{12142, 30435}, {12341, 30355},
+{12540, 30274}, {12738, 30191},
+{12935, 30107}, {13132, 30022},
+{13328, 29935}, {13524, 29847},
+{13719, 29758}, {13913, 29668},
+{14107, 29576}, {14300, 29483},
+{14493, 29389}, {14685, 29293},
+{14876, 29197}, {15067, 29099},
+{15257, 28999}, {15447, 28899},
+{15636, 28797}, {15824, 28694},
+{16011, 28590}, {16198, 28485},
+{16384, 28378}, {16569, 28270},
+{16754, 28161}, {16938, 28051},
+{17121, 27939}, {17304, 27827},
+{17485, 27713}, {17666, 27598},
+{17847, 27482}, {18026, 27364},
+{18205, 27246}, {18383, 27126},
+{18560, 27005}, {18736, 26883},
+{18912, 26760}, {19087, 26635},
+{19261, 26510}, {19434, 26383},
+{19606, 26255}, {19777, 26127},
+{19948, 25997}, {20118, 25865},
+{20286, 25733}, {20454, 25600},
+{20622, 25466}, {20788, 25330},
+{20953, 25193}, {21118, 25056},
+{21281, 24917}, {21444, 24777},
+{21605, 24636}, {21766, 24494},
+{21926, 24351}, {22085, 24207},
+{22243, 24062}, {22400, 23916},
+{22556, 23769}, {22711, 23621},
+{22865, 23472}, {23018, 23322},
+{23170, 23170}, {23322, 23018},
+{23472, 22865}, {23621, 22711},
+{23769, 22556}, {23916, 22400},
+{24062, 22243}, {24207, 22085},
+{24351, 21926}, {24494, 21766},
+{24636, 21605}, {24777, 21444},
+{24917, 21281}, {25056, 21118},
+{25193, 20953}, {25330, 20788},
+{25466, 20622}, {25600, 20454},
+{25733, 20286}, {25865, 20118},
+{25997, 19948}, {26127, 19777},
+{26255, 19606}, {26383, 19434},
+{26510, 19261}, {26635, 19087},
+{26760, 18912}, {26883, 18736},
+{27005, 18560}, {27126, 18383},
+{27246, 18205}, {27364, 18026},
+{27482, 17847}, {27598, 17666},
+{27713, 17485}, {27827, 17304},
+{27939, 17121}, {28051, 16938},
+{28161, 16754}, {28270, 16569},
+{28378, 16384}, {28485, 16198},
+{28590, 16011}, {28694, 15824},
+{28797, 15636}, {28899, 15447},
+{28999, 15257}, {29099, 15067},
+{29197, 14876}, {29293, 14685},
+{29389, 14493}, {29483, 14300},
+{29576, 14107}, {29668, 13913},
+{29758, 13719}, {29847, 13524},
+{29935, 13328}, {30022, 13132},
+{30107, 12935}, {30191, 12738},
+{30274, 12540}, {30355, 12341},
+{30435, 12142}, {30514, 11943},
+{30592, 11743}, {30668, 11543},
+{30743, 11342}, {30816, 11140},
+{30888, 10938}, {30959, 10736},
+{31029, 10533}, {31097, 10330},
+{31164, 10126}, {31230, 9922},
+{31294, 9717}, {31357, 9512},
+{31419, 9307}, {31479, 9101},
+{31538, 8895}, {31595, 8688},
+{31651, 8481}, {31706, 8274},
+{31760, 8066}, {31812, 7858},
+{31863, 7650}, {31912, 7441},
+{31960, 7232}, {32007, 7022},
+{32052, 6813}, {32096, 6603},
+{32138, 6393}, {32180, 6182},
+{32219, 5971}, {32258, 5760},
+{32295, 5549}, {32330, 5338},
+{32365, 5126}, {32397, 4914},
+{32429, 4702}, {32459, 4490},
+{32488, 4277}, {32515, 4064},
+{32541, 3851}, {32565, 3638},
+{32588, 3425}, {32610, 3212},
+{32631, 2998}, {32649, 2785},
+{32667, 2571}, {32683, 2357},
+{32698, 2143}, {32711, 1929},
+{32723, 1715}, {32734, 1501},
+{32743, 1286}, {32750, 1072},
+{32757, 858}, {32762, 643},
+{32765, 429}, {32767, 214},
+#endif
+};
+#ifndef FFT_BITREV960
+#define FFT_BITREV960
+static const opus_int16 fft_bitrev960[960] = {
+0, 192, 384, 576, 768, 64, 256, 448, 640, 832, 128, 320, 512, 704, 896,
+16, 208, 400, 592, 784, 80, 272, 464, 656, 848, 144, 336, 528, 720, 912,
+32, 224, 416, 608, 800, 96, 288, 480, 672, 864, 160, 352, 544, 736, 928,
+48, 240, 432, 624, 816, 112, 304, 496, 688, 880, 176, 368, 560, 752, 944,
+4, 196, 388, 580, 772, 68, 260, 452, 644, 836, 132, 324, 516, 708, 900,
+20, 212, 404, 596, 788, 84, 276, 468, 660, 852, 148, 340, 532, 724, 916,
+36, 228, 420, 612, 804, 100, 292, 484, 676, 868, 164, 356, 548, 740, 932,
+52, 244, 436, 628, 820, 116, 308, 500, 692, 884, 180, 372, 564, 756, 948,
+8, 200, 392, 584, 776, 72, 264, 456, 648, 840, 136, 328, 520, 712, 904,
+24, 216, 408, 600, 792, 88, 280, 472, 664, 856, 152, 344, 536, 728, 920,
+40, 232, 424, 616, 808, 104, 296, 488, 680, 872, 168, 360, 552, 744, 936,
+56, 248, 440, 632, 824, 120, 312, 504, 696, 888, 184, 376, 568, 760, 952,
+12, 204, 396, 588, 780, 76, 268, 460, 652, 844, 140, 332, 524, 716, 908,
+28, 220, 412, 604, 796, 92, 284, 476, 668, 860, 156, 348, 540, 732, 924,
+44, 236, 428, 620, 812, 108, 300, 492, 684, 876, 172, 364, 556, 748, 940,
+60, 252, 444, 636, 828, 124, 316, 508, 700, 892, 188, 380, 572, 764, 956,
+1, 193, 385, 577, 769, 65, 257, 449, 641, 833, 129, 321, 513, 705, 897,
+17, 209, 401, 593, 785, 81, 273, 465, 657, 849, 145, 337, 529, 721, 913,
+33, 225, 417, 609, 801, 97, 289, 481, 673, 865, 161, 353, 545, 737, 929,
+49, 241, 433, 625, 817, 113, 305, 497, 689, 881, 177, 369, 561, 753, 945,
+5, 197, 389, 581, 773, 69, 261, 453, 645, 837, 133, 325, 517, 709, 901,
+21, 213, 405, 597, 789, 85, 277, 469, 661, 853, 149, 341, 533, 725, 917,
+37, 229, 421, 613, 805, 101, 293, 485, 677, 869, 165, 357, 549, 741, 933,
+53, 245, 437, 629, 821, 117, 309, 501, 693, 885, 181, 373, 565, 757, 949,
+9, 201, 393, 585, 777, 73, 265, 457, 649, 841, 137, 329, 521, 713, 905,
+25, 217, 409, 601, 793, 89, 281, 473, 665, 857, 153, 345, 537, 729, 921,
+41, 233, 425, 617, 809, 105, 297, 489, 681, 873, 169, 361, 553, 745, 937,
+57, 249, 441, 633, 825, 121, 313, 505, 697, 889, 185, 377, 569, 761, 953,
+13, 205, 397, 589, 781, 77, 269, 461, 653, 845, 141, 333, 525, 717, 909,
+29, 221, 413, 605, 797, 93, 285, 477, 669, 861, 157, 349, 541, 733, 925,
+45, 237, 429, 621, 813, 109, 301, 493, 685, 877, 173, 365, 557, 749, 941,
+61, 253, 445, 637, 829, 125, 317, 509, 701, 893, 189, 381, 573, 765, 957,
+2, 194, 386, 578, 770, 66, 258, 450, 642, 834, 130, 322, 514, 706, 898,
+18, 210, 402, 594, 786, 82, 274, 466, 658, 850, 146, 338, 530, 722, 914,
+34, 226, 418, 610, 802, 98, 290, 482, 674, 866, 162, 354, 546, 738, 930,
+50, 242, 434, 626, 818, 114, 306, 498, 690, 882, 178, 370, 562, 754, 946,
+6, 198, 390, 582, 774, 70, 262, 454, 646, 838, 134, 326, 518, 710, 902,
+22, 214, 406, 598, 790, 86, 278, 470, 662, 854, 150, 342, 534, 726, 918,
+38, 230, 422, 614, 806, 102, 294, 486, 678, 870, 166, 358, 550, 742, 934,
+54, 246, 438, 630, 822, 118, 310, 502, 694, 886, 182, 374, 566, 758, 950,
+10, 202, 394, 586, 778, 74, 266, 458, 650, 842, 138, 330, 522, 714, 906,
+26, 218, 410, 602, 794, 90, 282, 474, 666, 858, 154, 346, 538, 730, 922,
+42, 234, 426, 618, 810, 106, 298, 490, 682, 874, 170, 362, 554, 746, 938,
+58, 250, 442, 634, 826, 122, 314, 506, 698, 890, 186, 378, 570, 762, 954,
+14, 206, 398, 590, 782, 78, 270, 462, 654, 846, 142, 334, 526, 718, 910,
+30, 222, 414, 606, 798, 94, 286, 478, 670, 862, 158, 350, 542, 734, 926,
+46, 238, 430, 622, 814, 110, 302, 494, 686, 878, 174, 366, 558, 750, 942,
+62, 254, 446, 638, 830, 126, 318, 510, 702, 894, 190, 382, 574, 766, 958,
+3, 195, 387, 579, 771, 67, 259, 451, 643, 835, 131, 323, 515, 707, 899,
+19, 211, 403, 595, 787, 83, 275, 467, 659, 851, 147, 339, 531, 723, 915,
+35, 227, 419, 611, 803, 99, 291, 483, 675, 867, 163, 355, 547, 739, 931,
+51, 243, 435, 627, 819, 115, 307, 499, 691, 883, 179, 371, 563, 755, 947,
+7, 199, 391, 583, 775, 71, 263, 455, 647, 839, 135, 327, 519, 711, 903,
+23, 215, 407, 599, 791, 87, 279, 471, 663, 855, 151, 343, 535, 727, 919,
+39, 231, 423, 615, 807, 103, 295, 487, 679, 871, 167, 359, 551, 743, 935,
+55, 247, 439, 631, 823, 119, 311, 503, 695, 887, 183, 375, 567, 759, 951,
+11, 203, 395, 587, 779, 75, 267, 459, 651, 843, 139, 331, 523, 715, 907,
+27, 219, 411, 603, 795, 91, 283, 475, 667, 859, 155, 347, 539, 731, 923,
+43, 235, 427, 619, 811, 107, 299, 491, 683, 875, 171, 363, 555, 747, 939,
+59, 251, 443, 635, 827, 123, 315, 507, 699, 891, 187, 379, 571, 763, 955,
+15, 207, 399, 591, 783, 79, 271, 463, 655, 847, 143, 335, 527, 719, 911,
+31, 223, 415, 607, 799, 95, 287, 479, 671, 863, 159, 351, 543, 735, 927,
+47, 239, 431, 623, 815, 111, 303, 495, 687, 879, 175, 367, 559, 751, 943,
+63, 255, 447, 639, 831, 127, 319, 511, 703, 895, 191, 383, 575, 767, 959,
+};
+#endif
+
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_0
+#define FFT_STATE96000_1920_0
+static const kiss_fft_state fft_state96000_1920_0 = {
+960,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+9,    /* scale_shift */
+-1,    /* shift */
+{5, 192, 3, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev960,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_960,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_1
+#define FFT_STATE96000_1920_1
+static const kiss_fft_state fft_state96000_1920_1 = {
+480,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+8,    /* scale_shift */
+1,    /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev480,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_2
+#define FFT_STATE96000_1920_2
+static const kiss_fft_state fft_state96000_1920_2 = {
+240,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+7,    /* scale_shift */
+2,    /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev240,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_3
+#define FFT_STATE96000_1920_3
+static const kiss_fft_state fft_state96000_1920_3 = {
+120,    /* nfft */
+#ifdef ENABLE_QEXT
+572662306,    /* scale */
+#else
+17476,    /* scale */
+#endif
+6,    /* scale_shift */
+3,    /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev120,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES1920
+#define MDCT_TWIDDLES1920
+static const celt_coef mdct_twiddles1920[3600] = {
+#ifdef ENABLE_QEXT
+2147483603, 2147480010, 2147470667, 2147455575, 2147434733,
+2147408142, 2147375802, 2147337712, 2147293874, 2147244286,
+2147188950, 2147127865, 2147061032, 2146988450, 2146910120,
+2146826042, 2146736216, 2146640643, 2146539323, 2146432256,
+2146319442, 2146200882, 2146076576, 2145946524, 2145810727,
+2145669185, 2145521898, 2145368867, 2145210092, 2145045574,
+2144875313, 2144699310, 2144517564, 2144330077, 2144136849,
+2143937880, 2143733172, 2143522724, 2143306537, 2143084612,
+2142856949, 2142623549, 2142384413, 2142139541, 2141888933,
+2141632592, 2141370516, 2141102708, 2140829167, 2140549894,
+2140264890, 2139974157, 2139677694, 2139375502, 2139067583,
+2138753936, 2138434564, 2138109466, 2137778644, 2137442099,
+2137099831, 2136751841, 2136398131, 2136038701, 2135673552,
+2135302685, 2134926101, 2134543801, 2134155787, 2133762059,
+2133362618, 2132957466, 2132546603, 2132130030, 2131707749,
+2131279761, 2130846067, 2130406668, 2129961565, 2129510759,
+2129054253, 2128592046, 2128124140, 2127650537, 2127171237,
+2126686242, 2126195553, 2125699172, 2125197100, 2124689338,
+2124175888, 2123656750, 2123131927, 2122601420, 2122065230,
+2121523358, 2120975806, 2120422576, 2119863669, 2119299086,
+2118728830, 2118152901, 2117571301, 2116984031, 2116391094,
+2115792491, 2115188222, 2114578291, 2113962699, 2113341447,
+2112714537, 2112081970, 2111443749, 2110799875, 2110150349,
+2109495174, 2108834352, 2108167883, 2107495770, 2106818015,
+2106134619, 2105445584, 2104750913, 2104050606, 2103344666,
+2102633095, 2101915895, 2101193067, 2100464614, 2099730537,
+2098990838, 2098245520, 2097494584, 2096738032, 2095975867,
+2095208091, 2094434705, 2093655711, 2092871112, 2092080910,
+2091285107, 2090483704, 2089676705, 2088864111, 2088045925,
+2087222148, 2086392783, 2085557833, 2084717298, 2083871182,
+2083019487, 2082162216, 2081299369, 2080430950, 2079556962,
+2078677406, 2077792284, 2076901600, 2076005355, 2075103552,
+2074196194, 2073283282, 2072364819, 2071440808, 2070511251,
+2069576151, 2068635510, 2067689330, 2066737615, 2065780367,
+2064817587, 2063849280, 2062875447, 2061896091, 2060911215,
+2059920821, 2058924912, 2057923491, 2056916560, 2055904122,
+2054886179, 2053862736, 2052833793, 2051799354, 2050759422,
+2049714000, 2048663090, 2047606695, 2046544818, 2045477461,
+2044404629, 2043326323, 2042242546, 2041153301, 2040058592,
+2038958421, 2037852791, 2036741705, 2035625166, 2034503177,
+2033375742, 2032242862, 2031104541, 2029960782, 2028811589,
+2027656964, 2026496910, 2025331431, 2024160529, 2022984208,
+2021802471, 2020615320, 2019422760, 2018224794, 2017021424,
+2015812654, 2014598487, 2013378926, 2012153975, 2010923636,
+2009687914, 2008446811, 2007200332, 2005948478, 2004691253,
+2003428662, 2002160707, 2000887391, 1999608718, 1998324692,
+1997035316, 1995740593, 1994440527, 1993135121, 1991824379,
+1990508304, 1989186900, 1987860170, 1986528118, 1985190748,
+1983848063, 1982500066, 1981146762, 1979788153, 1978424244,
+1977055038, 1975680539, 1974300751, 1972915676, 1971525320,
+1970129685, 1968728776, 1967322596, 1965911148, 1964494438,
+1963072467, 1961645241, 1960212764, 1958775038, 1957332067,
+1955883857, 1954430410, 1952971730, 1951507822, 1950038689,
+1948564335, 1947084764, 1945599980, 1944109987, 1942614790,
+1941114391, 1939608795, 1938098007, 1936582029, 1935060867,
+1933534524, 1932003004, 1930466312, 1928924452, 1927377427,
+1925825242, 1924267900, 1922705408, 1921137767, 1919564983,
+1917987059, 1916404001, 1914815812, 1913222496, 1911624058,
+1910020502, 1908411833, 1906798054, 1905179170, 1903555185,
+1901926103, 1900291930, 1898652669, 1897008325, 1895358902,
+1893704404, 1892044837, 1890380204, 1888710510, 1887035759,
+1885355956, 1883671105, 1881981211, 1880286279, 1878586312,
+1876881316, 1875171295, 1873456254, 1871736196, 1870011128,
+1868281053, 1866545976, 1864805901, 1863060834, 1861310779,
+1859555741, 1857795724, 1856030734, 1854260774, 1852485850,
+1850705966, 1848921127, 1847131338, 1845336604, 1843536929,
+1841732318, 1839922777, 1838108310, 1836288921, 1834464616,
+1832635400, 1830801277, 1828962253, 1827118332, 1825269519,
+1823415819, 1821557238, 1819693779, 1817825449, 1815952252,
+1814074193, 1812191278, 1810303510, 1808410896, 1806513440,
+1804611147, 1802704023, 1800792073, 1798875302, 1796953714,
+1795027315, 1793096111, 1791160105, 1789219305, 1787273714,
+1785323338, 1783368182, 1781408251, 1779443552, 1777474088,
+1775499865, 1773520888, 1771537164, 1769548696, 1767555491,
+1765557554, 1763554889, 1761547504, 1759535401, 1757518588,
+1755497070, 1753470852, 1751439939, 1749404337, 1747364051,
+1745319087, 1743269451, 1741215147, 1739156181, 1737092559,
+1735024287, 1732951369, 1730873811, 1728791620, 1726704800,
+1724613357, 1722517297, 1720416625, 1718311347, 1716201468,
+1714086995, 1711967933, 1709844287, 1707716063, 1705583268,
+1703445906, 1701303983, 1699157505, 1697006479, 1694850909,
+1692690801, 1690526161, 1688356996, 1686183310, 1684005110,
+1681822401, 1679635189, 1677443481, 1675247281, 1673046596,
+1670841433, 1668631795, 1666417691, 1664199124, 1661976103,
+1659748631, 1657516716, 1655280364, 1653039579, 1650794369,
+1648544739, 1646290696, 1644032245, 1641769393, 1639502145,
+1637230507, 1634954486, 1632674088, 1630389319, 1628100184,
+1625806691, 1623508845, 1621206653, 1618900119, 1616589252,
+1614274057, 1611954539, 1609630706, 1607302564, 1604970118,
+1602633375, 1600292342, 1597947024, 1595597428, 1593243560,
+1590885426, 1588523033, 1586156387, 1583785495, 1581410362,
+1579030995, 1576647401, 1574259586, 1571867556, 1569471317,
+1567070877, 1564666241, 1562257416, 1559844408, 1557427224,
+1555005871, 1552580354, 1550150681, 1547716857, 1545278889,
+1542836785, 1540390550, 1537940190, 1535485713, 1533027126,
+1530564434, 1528097644, 1525626762, 1523151797, 1520672753,
+1518189638, 1515702459, 1513211221, 1510715932, 1508216599,
+1505713227, 1503205824, 1500694397, 1498178952, 1495659496,
+1493136035, 1490608577, 1488077129, 1485541696, 1483002286,
+1480458905, 1477911561, 1475360260, 1472805009, 1470245815,
+1467682684, 1465115624, 1462544642, 1459969744, 1457390937,
+1454808228, 1452221624, 1449631133, 1447036760, 1444438513,
+1441836399, 1439230424, 1436620597, 1434006923, 1431389409,
+1428768064, 1426142893, 1423513904, 1420881104, 1418244500,
+1415604099, 1412959907, 1410311933, 1407660183, 1405004664,
+1402345384, 1399682349, 1397015567, 1394345044, 1391670789,
+1388992807, 1386311107, 1383625695, 1380936579, 1378243766,
+1375547262, 1372847076, 1370143215, 1367435685, 1364724494,
+1362009649, 1359291158, 1356569027, 1353843265, 1351113878,
+1348380873, 1345644259, 1342904042, 1340160229, 1337412829,
+1334661848, 1331907293, 1329149173, 1326387494, 1323622264,
+1320853490, 1318081180, 1315305341, 1312525981, 1309743106,
+1306956725, 1304166845, 1301373473, 1298576617, 1295776285,
+1292972483, 1290165219, 1287354501, 1284540337, 1281722734,
+1278901699, 1276077240, 1273249364, 1270418080, 1267583394,
+1264745315, 1261903850, 1259059006, 1256210791, 1253359213,
+1250504279, 1247645998, 1244784376, 1241919421, 1239051142,
+1236179545, 1233304638, 1230426430, 1227544927, 1224660138,
+1221772070, 1218880731, 1215986128, 1213088271, 1210187165,
+1207282819, 1204375241, 1201464439, 1198550419, 1195633191,
+1192712762, 1189789140, 1186862332, 1183932347, 1180999192,
+1178062875, 1175123404, 1172180786, 1169235031, 1166286145,
+1163334137, 1160379014, 1157420784, 1154459456, 1151495036,
+1148527534, 1145556957, 1142583313, 1139606610, 1136626856,
+1133644058, 1130658226, 1127669367, 1124677488, 1121682598,
+1118684705, 1115683818, 1112679943, 1109673089, 1106663264,
+1103650476, 1100634734, 1097616045, 1094594417, 1091569858,
+1088542378, 1085511982, 1082478681, 1079442481, 1076403392,
+1073361420, 1070316575, 1067268864, 1064218296, 1061164879,
+1058108621, 1055049529, 1051987613, 1048922881, 1045855340,
+1042784999, 1039711867, 1036635950, 1033557259, 1030475800,
+1027391582, 1024304614, 1021214903, 1018122458, 1015027288,
+1011929400, 1008828802, 1005725504, 1002619513, 999510838,
+996399486, 993285468, 990168789, 987049460, 983927488,
+980802882, 977675650, 974545800, 971413342, 968278282,
+965140630, 962000395, 958857583, 955712205, 952564267,
+949413780, 946260750, 943105188, 939947100, 936786495,
+933623383, 930457771, 927289668, 924119082, 920946022,
+917770497, 914592514, 911412082, 908229211, 905043908,
+901856182, 898666041, 895473494, 892278550, 889081217,
+885881504, 882679419, 879474970, 876268167, 873059018,
+869847532, 866633717, 863417581, 860199134, 856978384,
+853755339, 850530009, 847302402, 844072526, 840840390,
+837606003, 834369373, 831130510, 827889422, 824646117,
+821400604, 818152892, 814902989, 811650905, 808396648,
+805140227, 801881649, 798620925, 795358063, 792093072,
+788825960, 785556735, 782285408, 779011986, 775736479,
+772458895, 769179242, 765897531, 762613768, 759327964,
+756040127, 752750266, 749458390, 746164507, 742868626,
+739570757, 736270907, 732969086, 729665303, 726359567,
+723051885, 719742268, 716430724, 713117261, 709801890,
+706484618, 703165455, 699844409, 696521489, 693196705,
+689870064, 686541577, 683211252, 679879097, 676545122,
+673209336, 669871748, 666532366, 663191199, 659848257,
+656503549, 653157082, 649808867, 646458913, 643107227,
+639753820, 636398700, 633041876, 629683357, 626323153,
+622961271, 619597722, 616232514, 612865656, 609497157,
+606127026, 602755273, 599381905, 596006934, 592630366,
+589252212, 585872480, 582491179, 579108320, 575723909,
+572337957, 568950473, 565561466, 562170945, 558778918,
+555385395, 551990386, 548593898, 545195942, 541796526,
+538395660, 534993352, 531589612, 528184449, 524777871,
+521369889, 517960510, 514549745, 511137603, 507724092,
+504309221, 500893000, 497475439, 494056545, 490636329,
+487214799, 483791965, 480367835, 476942419, 473515727,
+470087766, 466658548, 463228079, 459796371, 456363431,
+452929270, 449493896, 446057319, 442619547, 439180590,
+435740458, 432299159, 428856702, 425413098, 421968354,
+418522481, 415075487, 411627382, 408178175, 404727875,
+401276491, 397824033, 394370510, 390915931, 387460306,
+384003643, 380545952, 377087242, 373627523, 370166803,
+366705093, 363242400, 359778735, 356314107, 352848525,
+349381998, 345914536, 342446148, 338976842, 335506630,
+332035519, 328563519, 325090639, 321616889, 318142278,
+314666815, 311190510, 307713372, 304235410, 300756633,
+297277051, 293796673, 290315508, 286833567, 283350857,
+279867389, 276383171, 272898214, 269412525, 265926116,
+262438995, 258951170, 255462653, 251973452, 248483576,
+244993035, 241501838, 238009994, 234517513, 231024404,
+227530677, 224036341, 220541404, 217045878, 213549770,
+210053090, 206555848, 203058053, 199559715, 196060842,
+192561444, 189061531, 185561111, 182060195, 178558791,
+175056909, 171554559, 168051749, 164548489, 161044789,
+157540658, 154036105, 150531139, 147025770, 143520008,
+140013862, 136507340, 133000453, 129493210, 125985621,
+122477694, 118969439, 115460866, 111951983, 108442801,
+104933329, 101423575, 97913550, 94403263, 90892723,
+87381940, 83870923, 80359681, 76848224, 73336562,
+69824703, 66312657, 62800433, 59288042, 55775491,
+52262792, 48749952, 45236982, 41723891, 38210688,
+34697383, 31183985, 27670503, 24156947, 20643327,
+17129651, 13615930, 10102172, 6588387, 3074584,
+-439226, -3953036, -7466835, -10980614, -14494364,
+-18008075, -21521738, -25035343, -28548881, -32062342,
+-35575718, -39088999, -42602174, -46115236, -49628175,
+-53140980, -56653643, -60166155, -63678505, -67190685,
+-70702685, -74214496, -77726108, -81237512, -84748698,
+-88259658, -91770381, -95280859, -98791081, -102301039,
+-105810723, -109320124, -112829232, -116338038, -119846533,
+-123354707, -126862550, -130370054, -133877209, -137384005,
+-140890434, -144396485, -147902150, -151407418, -154912282,
+-158416730, -161920755, -165424346, -168927494, -172430190,
+-175932424, -179434187, -182935470, -186436263, -189936557,
+-193436342, -196935610, -200434350, -203932553, -207430211,
+-210927313, -214423851, -217919814, -221415194, -224909981,
+-228404166, -231897740, -235390693, -238883015, -242374698,
+-245865732, -249356108, -252845816, -256334847, -259823192,
+-263310841, -266797785, -270284015, -273769522, -277254295,
+-280738326, -284221606, -287704124, -291185873, -294666841,
+-298147021, -301626403, -305104977, -308582734, -312059665,
+-315535760, -319011011, -322485408, -325958941, -329431602,
+-332903380, -336374268, -339844254, -343313331, -346781489,
+-350248718, -353715010, -357180354, -360644742, -364108165,
+-367570613, -371032077, -374492547, -377952015, -381410471,
+-384867905, -388324310, -391779674, -395233990, -398687248,
+-402139438, -405590552, -409040579, -412489512, -415937340,
+-419384055, -422829646, -426274106, -429717424, -433159592,
+-436600601, -440040440, -443479101, -446916575, -450352853,
+-453787924, -457221781, -460654414, -464085813, -467515970,
+-470944875, -474372519, -477798893, -481223988, -484647795,
+-488070304, -491491506, -494911393, -498329954, -501747182,
+-505163066, -508577597, -511990767, -515402566, -518812985,
+-522222016, -525629648, -529035873, -532440681, -535844064,
+-539246012, -542646517, -546045568, -549443158, -552839277,
+-556233916, -559627065, -563018716, -566408860, -569797488,
+-573184589, -576570157, -579954180, -583336651, -586717560,
+-590096899, -593474657, -596850827, -600225398, -603598363,
+-606969711, -610339435, -613707524, -617073971, -620438765,
+-623801898, -627163361, -630523145, -633881241, -637237640,
+-640592333, -643945310, -647296564, -650646085, -653993863,
+-657339891, -660684159, -664026658, -667367379, -670706313,
+-674043452, -677378786, -680712307, -684044005, -687373872,
+-690701898, -694028075, -697352394, -700674846, -703995422,
+-707314114, -710630911, -713945806, -717258790, -720569853,
+-723878987, -727186183, -730491433, -733794726, -737096055,
+-740395410, -743692783, -746988165, -750281547, -753572921,
+-756862277, -760149606, -763434901, -766718151, -769999349,
+-773278485, -776555551, -779830538, -783103437, -786374239,
+-789642936, -792909519, -796173979, -799436307, -802696495,
+-805954534, -809210416, -812464130, -815715670, -818965026,
+-822212189, -825457150, -828699902, -831940435, -835178741,
+-838414810, -841648635, -844880207, -848109516, -851336555,
+-854561315, -857783787, -861003962, -864221832, -867437388,
+-870650622, -873861525, -877070088, -880276304, -883480162,
+-886681655, -889880774, -893077511, -896271856, -899463802,
+-902653340, -905840461, -909025157, -912207419, -915387239,
+-918564609, -921739519, -924911961, -928081927, -931249408,
+-934414396, -937576882, -940736858, -943894315, -947049246,
+-950201640, -953351491, -956498790, -959643527, -962785695,
+-965925286, -969062291, -972196701, -975328508, -978457704,
+-981584280, -984708228, -987829540, -990948208, -994064222,
+-997177575, -1000288258, -1003396263, -1006501581, -1009604205,
+-1012704126, -1015801336, -1018895826, -1021987588, -1025076613,
+-1028162895, -1031246424, -1034327191, -1037405190, -1040480411,
+-1043552847, -1046622488, -1049689328, -1052753357, -1055814567,
+-1058872951, -1061928500, -1064981206, -1068031060, -1071078055,
+-1074122183, -1077163435, -1080201802, -1083237278, -1086269854,
+-1089299521, -1092326272, -1095350099, -1098370993, -1101388946,
+-1104403951, -1107415998, -1110425081, -1113431191, -1116434320,
+-1119434460, -1122431603, -1125425740, -1128416865, -1131404968,
+-1134390043, -1137372080, -1140351072, -1143327011, -1146299889,
+-1149269698, -1152236431, -1155200078, -1158160632, -1161118086,
+-1164072431, -1167023660, -1169971764, -1172916735, -1175858567,
+-1178797250, -1181732777, -1184665141, -1187594332, -1190520344,
+-1193443169, -1196362799, -1199279225, -1202192441, -1205102438,
+-1208009209, -1210912745, -1213813040, -1216710085, -1219603872,
+-1222494394, -1225381643, -1228265611, -1231146291, -1234023675,
+-1236897754, -1239768523, -1242635972, -1245500094, -1248360882,
+-1251218327, -1254072422, -1256923160, -1259770533, -1262614533,
+-1265455153, -1268292384, -1271126220, -1273956653, -1276783675,
+-1279607279, -1282427457, -1285244201, -1288057504, -1290867359,
+-1293673758, -1296476693, -1299276157, -1302072143, -1304864643,
+-1307653649, -1310439154, -1313221151, -1315999631, -1318774589,
+-1321546016, -1324313904, -1327078247, -1329839037, -1332596266,
+-1335349928, -1338100015, -1340846519, -1343589433, -1346328751,
+-1349064463, -1351796564, -1354525046, -1357249901, -1359971122,
+-1362688702, -1365402634, -1368112911, -1370819524, -1373522468,
+-1376221734, -1378917315, -1381609205, -1384297396, -1386981880,
+-1389662652, -1392339702, -1395013025, -1397682613, -1400348459,
+-1403010556, -1405668897, -1408323474, -1410974281, -1413621310,
+-1416264555, -1418904007, -1421539661, -1424171509, -1426799544,
+-1429423759, -1432044147, -1434660701, -1437273414, -1439882279,
+-1442487289, -1445088437, -1447685717, -1450279120, -1452868640,
+-1455454271, -1458036005, -1460613835, -1463187755, -1465757757,
+-1468323835, -1470885982, -1473444191, -1475998456, -1478548768,
+-1481095122, -1483637511, -1486175927, -1488710365, -1491240816,
+-1493767276, -1496289736, -1498808190, -1501322631, -1503833053,
+-1506339448, -1508841811, -1511340134, -1513834411, -1516324634,
+-1518810798, -1521292896, -1523770921, -1526244866, -1528714725,
+-1531180491, -1533642158, -1536099718, -1538553166, -1541002495,
+-1543447698, -1545888769, -1548325701, -1550758488, -1553187123,
+-1555611600, -1558031911, -1560448052, -1562860014, -1565267793,
+-1567671380, -1570070771, -1572465958, -1574856935, -1577243696,
+-1579626234, -1582004542, -1584378616, -1586748447, -1589114030,
+-1591475359, -1593832427, -1596185227, -1598533754, -1600878002,
+-1603217963, -1605553632, -1607885003, -1610212069, -1612534823,
+-1614853261, -1617167375, -1619477159, -1621782608, -1624083714,
+-1626380473, -1628672877, -1630960921, -1633244598, -1635523902,
+-1637798828, -1640069368, -1642335518, -1644597271, -1646854620,
+-1649107561, -1651356086, -1653600190, -1655839867, -1658075111,
+-1660305916, -1662532275, -1664754184, -1666971635, -1669184624,
+-1671393143, -1673597188, -1675796752, -1677991829, -1680182414,
+-1682368500, -1684550083, -1686727155, -1688899711, -1691067746,
+-1693231253, -1695390227, -1697544662, -1699694551, -1701839891,
+-1703980674, -1706116895, -1708248548, -1710375628, -1712498128,
+-1714616044, -1716729369, -1718838098, -1720942225, -1723041744,
+-1725136651, -1727226938, -1729312602, -1731393635, -1733470033,
+-1735541790, -1737608901, -1739671359, -1741729160, -1743782298,
+-1745830767, -1747874561, -1749913677, -1751948107, -1753977847,
+-1756002891, -1758023233, -1760038869, -1762049792, -1764055998,
+-1766057481, -1768054236, -1770046258, -1772033540, -1774016078,
+-1775993866, -1777966900, -1779935173, -1781898681, -1783857419,
+-1785811380, -1787760560, -1789704954, -1791644556, -1793579362,
+-1795509366, -1797434562, -1799354946, -1801270513, -1803181257,
+-1805087174, -1806988258, -1808884503, -1810775906, -1812662462,
+-1814544164, -1816421007, -1818292988, -1820160101, -1822022340,
+-1823879702, -1825732180, -1827579771, -1829422468, -1831260267,
+-1833093164, -1834921153, -1836744229, -1838562388, -1840375624,
+-1842183933, -1843987310, -1845785751, -1847579249, -1849367801,
+-1851151401, -1852930046, -1854703729, -1856472447, -1858236195,
+-1859994968, -1861748761, -1863497569, -1865241388, -1866980214,
+-1868714041, -1870442864, -1872166681, -1873885484, -1875599271,
+-1877308036, -1879011776, -1880710484, -1882404157, -1884092791,
+-1885776380, -1887454920, -1889128407, -1890796837, -1892460204,
+-1894118504, -1895771734, -1897419887, -1899062961, -1900700951,
+-1902333851, -1903961659, -1905584369, -1907201977, -1908814479,
+-1910421871, -1912024148, -1913621306, -1915213340, -1916800247,
+-1918382022, -1919958661, -1921530159, -1923096514, -1924657719,
+-1926213771, -1927764667, -1929310401, -1930850970, -1932386369,
+-1933916595, -1935441643, -1936961510, -1938476190, -1939985681,
+-1941489978, -1942989077, -1944482974, -1945971664, -1947455145,
+-1948933412, -1950406461, -1951874289, -1953336890, -1954794262,
+-1956246401, -1957693301, -1959134961, -1960571375, -1962002540,
+-1963428453, -1964849109, -1966264504, -1967674635, -1969079498,
+-1970479089, -1971873404, -1973262440, -1974646194, -1976024660,
+-1977397836, -1978765718, -1980128302, -1981485585, -1982837563,
+-1984184232, -1985525589, -1986861630, -1988192351, -1989517750,
+-1990837822, -1992152564, -1993461973, -1994766044, -1996064775,
+-1997358161, -1998646200, -1999928888, -2001206222, -2002478198,
+-2003744813, -2005006063, -2006261945, -2007512455, -2008757591,
+-2009997349, -2011231726, -2012460718, -2013684322, -2014902534,
+-2016115352, -2017322773, -2018524792, -2019721407, -2020912615,
+-2022098413, -2023278796, -2024453763, -2025623309, -2026787432,
+-2027946129, -2029099397, -2030247232, -2031389631, -2032526592,
+-2033658111, -2034784185, -2035904812, -2037019988, -2038129710,
+-2039233976, -2040332782, -2041426125, -2042514003, -2043596412,
+-2044673350, -2045744814, -2046810801, -2047871308, -2048926332,
+-2049975870, -2051019920, -2052058479, -2053091544, -2054119112,
+-2055141181, -2056157747, -2057168809, -2058174363, -2059174406,
+-2060168936, -2061157951, -2062141448, -2063119423, -2064091875,
+-2065058800, -2066020197, -2066976063, -2067926394, -2068871190,
+-2069810446, -2070744160, -2071672331, -2072594955, -2073512030,
+-2074423554, -2075329524, -2076229937, -2077124792, -2078014086,
+-2078897817, -2079775981, -2080648577, -2081515603, -2082377056,
+-2083232934, -2084083234, -2084927955, -2085767094, -2086600648,
+-2087428616, -2088250996, -2089067784, -2089878979, -2090684580,
+-2091484582, -2092278986, -2093067787, -2093850985, -2094628577,
+-2095400561, -2096166935, -2096927697, -2097682844, -2098432376,
+-2099176290, -2099914583, -2100647254, -2101374302, -2102095723,
+-2102811516, -2103521679, -2104226211, -2104925109, -2105618372,
+-2106305997, -2106987983, -2107664327, -2108335029, -2109000087,
+-2109659498, -2110313260, -2110961373, -2111603834, -2112240642,
+-2112871795, -2113497290, -2114117128, -2114731305, -2115339820,
+-2115942673, -2116539860, -2117131380, -2117717232, -2118297415,
+-2118871926, -2119440764, -2120003928, -2120561416, -2121113227,
+-2121659358, -2122199810, -2122734579, -2123263666, -2123787068,
+-2124304784, -2124816812, -2125323152, -2125823801, -2126318759,
+-2126808025, -2127291596, -2127769472, -2128241651, -2128708132,
+-2129168914, -2129623995, -2130073375, -2130517052, -2130955025,
+-2131387293, -2131813854, -2132234708, -2132649854, -2133059289,
+-2133463014, -2133861027, -2134253326, -2134639912, -2135020783,
+-2135395937, -2135765375, -2136129094, -2136487095, -2136839375,
+-2137185934, -2137526772, -2137861886, -2138191277, -2138514944,
+-2138832885, -2139145099, -2139451587, -2139752346, -2140047377,
+-2140336678, -2140620249, -2140898089, -2141170197, -2141436573,
+-2141697215, -2141952123, -2142201296, -2142444735, -2142682437,
+-2142914403, -2143140631, -2143361122, -2143575874, -2143784887,
+-2143988161, -2144185694, -2144377487, -2144563539, -2144743849,
+-2144918417, -2145087242, -2145250325, -2145407663, -2145559258,
+-2145705109, -2145845215, -2145979576, -2146108191, -2146231061,
+-2146348185, -2146459562, -2146565192, -2146665076, -2146759212,
+-2146847600, -2146930241, -2147007134, -2147078279, -2147143675,
+-2147203323, -2147257222, -2147305372, -2147347773, -2147384426,
+-2147415329, -2147440482, -2147459887, -2147473542, -2147481447,
+2147483468, 2147469095, 2147431723, 2147371355, 2147287990,
+2147181629, 2147052273, 2146899924, 2146724584, 2146526254,
+2146304937, 2146060634, 2145793349, 2145503083, 2145189842,
+2144853627, 2144494442, 2144112292, 2143707180, 2143279110,
+2142828088, 2142354118, 2141857204, 2141337354, 2140794571,
+2140228862, 2139640233, 2139028690, 2138394240, 2137736889,
+2137056645, 2136353515, 2135627506, 2134878626, 2134106884,
+2133312286, 2132494843, 2131654563, 2130791454, 2129905526,
+2128996788, 2128065251, 2127110924, 2126133817, 2125133941,
+2124111307, 2123065925, 2121997806, 2120906963, 2119793407,
+2118657149, 2117498202, 2116316578, 2115112291, 2113885352,
+2112635775, 2111363574, 2110068761, 2108751352, 2107411359,
+2106048798, 2104663683, 2103256028, 2101825849, 2100373162,
+2098897981, 2097400322, 2095880202, 2094337637, 2092772643,
+2091185237, 2089575437, 2087943258, 2086288720, 2084611839,
+2082912633, 2081191122, 2079447322, 2077681253, 2075892934,
+2074082383, 2072249621, 2070394667, 2068517540, 2066618262,
+2064696851, 2062753329, 2060787717, 2058800036, 2056790306,
+2054758550, 2052704789, 2050629045, 2048531340, 2046411698,
+2044270140, 2042106689, 2039921369, 2037714204, 2035485216,
+2033234429, 2030961869, 2028667558, 2026351522, 2024013785,
+2021654373, 2019273310, 2016870623, 2014446336, 2012000477,
+2009533071, 2007044144, 2004533723, 2002001835, 1999448508,
+1996873768, 1994277643, 1991660161, 1989021350, 1986361238,
+1983679853, 1980977226, 1978253383, 1975508355, 1972742171,
+1969954860, 1967146453, 1964316979, 1961466469, 1958594953,
+1955702462, 1952789027, 1949854680, 1946899451, 1943923372,
+1940926475, 1937908793, 1934870357, 1931811201, 1928731356,
+1925630856, 1922509734, 1919368023, 1916205758, 1913022972,
+1909819698, 1906595972, 1903351828, 1900087301, 1896802425,
+1893497236, 1890171769, 1886826060, 1883460144, 1880074058,
+1876667838, 1873241521, 1869795142, 1866328740, 1862842350,
+1859336011, 1855809760, 1852263635, 1848697674, 1845111914,
+1841506395, 1837881155, 1834236233, 1830571667, 1826887497,
+1823183763, 1819460504, 1815717761, 1811955572, 1808173978,
+1804373021, 1800552740, 1796713177, 1792854372, 1788976368,
+1785079205, 1781162925, 1777227570, 1773273182, 1769299805,
+1765307479, 1761296249, 1757266156, 1753217244, 1749149557,
+1745063138, 1740958031, 1736834279, 1732691928, 1728531020,
+1724351602, 1720153717, 1715937410, 1711702727, 1707449714,
+1703178415, 1698888876, 1694581143, 1690255263, 1685911282,
+1681549245, 1677169201, 1672771196, 1668355276, 1663921490,
+1659469885, 1655000508, 1650513407, 1646008631, 1641486227,
+1636946244, 1632388731, 1627813736, 1623221309, 1618611498,
+1613984353, 1609339924, 1604678260, 1599999411, 1595303428,
+1590590360, 1585860258, 1581113173, 1576349155, 1571568256,
+1566770527, 1561956018, 1557124783, 1552276872, 1547412337,
+1542531231, 1537633606, 1532719513, 1527789007, 1522842139,
+1517878963, 1512899531, 1507903898, 1502892116, 1497864239,
+1492820322, 1487760417, 1482684580, 1477592864, 1472485325,
+1467362016, 1462222994, 1457068312, 1451898025, 1446712191,
+1441510863, 1436294098, 1431061951, 1425814478, 1420551737,
+1415273782, 1409980671, 1404672460, 1399349206, 1394010966,
+1388657798, 1383289758, 1377906904, 1372509294, 1367096986,
+1361670037, 1356228505, 1350772450, 1345301929, 1339817000,
+1334317724, 1328804158, 1323276361, 1317734393, 1312178313,
+1306608181, 1301024057, 1295425999, 1289814068, 1284188325,
+1278548828, 1272895640, 1267228820, 1261548429, 1255854528,
+1250147177, 1244426439, 1238692373, 1232945043, 1227184508,
+1221410831, 1215624074, 1209824299, 1204011567, 1198185941,
+1192347484, 1186496258, 1180632325, 1174755748, 1168866591,
+1162964917, 1157050787, 1151124267, 1145185419, 1139234307,
+1133270995, 1127295547, 1121308026, 1115308496, 1109297023,
+1103273670, 1097238502, 1091191583, 1085132978, 1079062753,
+1072980972, 1066887699, 1060783002, 1054666944, 1048539592,
+1042401010, 1036251266, 1030090423, 1023918550, 1017735711,
+1011541973, 1005337402, 999122065, 992896028, 986659358,
+980412122, 974154386, 967886217, 961607684, 955318852,
+949019790, 942710564, 936391243, 930061894, 923722585,
+917373383, 911014357, 904645574, 898267104, 891879014,
+885481373, 879074249, 872657710, 866231826, 859796666,
+853352298, 846898791, 840436214, 833964638, 827484130,
+820994760, 814496598, 807989714, 801474176, 794950056,
+788417422, 781876345, 775326894, 768769141, 762203154,
+755629005, 749046764, 742456501, 735858287, 729252193,
+722638289, 716016646, 709387335, 702750427, 696105993,
+689454104, 682794832, 676128248, 669454423, 662773428,
+656085336, 649390218, 642688145, 635979190, 629263424,
+622540918, 615811746, 609075979, 602333690, 595584950,
+588829831, 582068407, 575300749, 568526931, 561747023,
+554961100, 548169234, 541371497, 534567963, 527758704,
+520943793, 514123303, 507297307, 500465878, 493629090,
+486787016, 479939728, 473087301, 466229807, 459367320,
+452499914, 445627662, 438750638, 431868915, 424982567,
+418091668, 411196291, 404296511, 397392401, 390484035,
+383571488, 376654833, 369734144, 362809495, 355880961,
+348948616, 342012534, 335072790, 328129457, 321182610,
+314232323, 307278671, 300321729, 293361570, 286398270,
+279431902, 272462542, 265490265, 258515144, 251537254,
+244556671, 237573469, 230587722, 223599506, 216608896,
+209615966, 202620791, 195623446, 188624006, 181622546,
+174619141, 167613866, 160606796, 153598006, 146587571,
+139575567, 132562067, 125547148, 118530885, 111513352,
+104494625, 97474778, 90453888, 83432030, 76409277,
+69385707, 62361393, 55336412, 48310838, 41284746,
+34258213, 27231312, 20204120, 13176712, 6149162,
+-878453, -7906059, -14933580, -21960942, -28988068,
+-36014884, -43041314, -50067283, -57092716, -64117537,
+-71141672, -78165045, -85187581, -92209205, -99229841,
+-106249414, -113267850, -120285073, -127301007, -134315578,
+-141328711, -148340330, -155350361, -162358728, -169365356,
+-176370170, -183373096, -190374058, -197372981, -204369791,
+-211364411, -218356769, -225346788, -232334393, -239319511,
+-246302065, -253281982, -260259186, -267233603, -274205159,
+-281173778, -288139385, -295101907, -302061269, -309017396,
+-315970213, -322919647, -329865622, -336808065, -343746901,
+-350682056, -357613455, -364541025, -371464690, -378384377,
+-385300013, -392211522, -399118830, -406021865, -412920551,
+-419814815, -426704583, -433589782, -440470337, -447346176,
+-454217223, -461083406, -467944652, -474800886, -481652035,
+-488498026, -495338786, -502174241, -509004318, -515828944,
+-522648046, -529461551, -536269386, -543071478, -549867754,
+-556658141, -563442567, -570220959, -576993244, -583759350,
+-590519205, -597272736, -604019870, -610760536, -617494660,
+-624222173, -630943000, -637657070, -644364312, -651064652,
+-657758021, -664444345, -671123554, -677795576, -684460338,
+-691117771, -697767803, -704410362, -711045377, -717672778,
+-724292493, -730904451, -737508582, -744104815, -750693079,
+-757273304, -763845419, -770409354, -776965038, -783512402,
+-790051375, -796581887, -803103868, -809617249, -816121959,
+-822617929, -829105090, -835583372, -842052705, -848513021,
+-854964249, -861406322, -867839170, -874262724, -880676915,
+-887081675, -893476935, -899862626, -906238681, -912605031,
+-918961607, -925308342, -931645168, -937972016, -944288820,
+-950595511, -956892022, -963178285, -969454234, -975719800,
+-981974918, -988219519, -994453537, -1000676905, -1006889557,
+-1013091426, -1019282445, -1025462549, -1031631671, -1037789745,
+-1043936705, -1050072485, -1056197020, -1062310244, -1068412091,
+-1074502497, -1080581395, -1086648722, -1092704411, -1098748398,
+-1104780618, -1110801008, -1116809501, -1122806034, -1128790543,
+-1134762964, -1140723232, -1146671283, -1152607055, -1158530484,
+-1164441505, -1170340057, -1176226074, -1182099496, -1187960258,
+-1193808298, -1199643553, -1205465961, -1211275460, -1217071986,
+-1222855479, -1228625876, -1234383115, -1240127136, -1245857875,
+-1251575272, -1257279266, -1262969796, -1268646800, -1274310217,
+-1279959989, -1285596052, -1291218348, -1296826816, -1302421396,
+-1308002029, -1313568653, -1319121210, -1324659641, -1330183885,
+-1335693885, -1341189580, -1346670912, -1352137822, -1357590252,
+-1363028143, -1368451438, -1373860077, -1379254004, -1384633159,
+-1389997487, -1395346928, -1400681427, -1406000925, -1411305366,
+-1416594694, -1421868850, -1427127780, -1432371426, -1437599733,
+-1442812644, -1448010104, -1453192057, -1458358447, -1463509220,
+-1468644319, -1473763690, -1478867279, -1483955030, -1489026889,
+-1494082802, -1499122714, -1504146572, -1509154322, -1514145910,
+-1519121283, -1524080387, -1529023170, -1533949577, -1538859558,
+-1543753058, -1548630027, -1553490410, -1558334157, -1563161216,
+-1567971534, -1572765060, -1577541744, -1582301533, -1587044377,
+-1591770225, -1596479027, -1601170732, -1605845289, -1610502649,
+-1615142762, -1619765578, -1624371047, -1628959121, -1633529750,
+-1638082885, -1642618478, -1647136479, -1651636841, -1656119516,
+-1660584454, -1665031609, -1669460933, -1673872378, -1678265898,
+-1682641444, -1686998971, -1691338432, -1695659779, -1699962968,
+-1704247951, -1708514683, -1712763118, -1716993211, -1721204917,
+-1725398189, -1729572984, -1733729257, -1737866963, -1741986057,
+-1746086497, -1750168237, -1754231234, -1758275445, -1762300826,
+-1766307335, -1770294927, -1774263561, -1778213194, -1782143784,
+-1786055289, -1789947667, -1793820875, -1797674873, -1801509620,
+-1805325074, -1809121194, -1812897940, -1816655271, -1820393147,
+-1824111529, -1827810376, -1831489648, -1835149306, -1838789312,
+-1842409625, -1846010208, -1849591022, -1853152028, -1856693188,
+-1860214464, -1863715819, -1867197215, -1870658615, -1874099982,
+-1877521279, -1880922469, -1884303515, -1887664383, -1891005035,
+-1894325435, -1897625550, -1900905342, -1904164776, -1907403819,
+-1910622435, -1913820590, -1916998250, -1920155379, -1923291946,
+-1926407915, -1929503255, -1932577931, -1935631910, -1938665161,
+-1941677650, -1944669345, -1947640214, -1950590226, -1953519348,
+-1956427550, -1959314800, -1962181067, -1965026321, -1967850531,
+-1970653667, -1973435699, -1976196596, -1978936331, -1981654873,
+-1984352192, -1987028261, -1989683050, -1992316532, -1994928677,
+-1997519459, -2000088848, -2002636818, -2005163342, -2007668391,
+-2010151941, -2012613963, -2015054432, -2017473321, -2019870604,
+-2022246257, -2024600252, -2026932566, -2029243173, -2031532049,
+-2033799168, -2036044507, -2038268042, -2040469748, -2042649603,
+-2044807583, -2046943664, -2049057824, -2051150040, -2053220291,
+-2055268553, -2057294804, -2059299024, -2061281190, -2063241282,
+-2065179277, -2067095157, -2068988899, -2070860485, -2072709893,
+-2074537104, -2076342098, -2078124857, -2079885360, -2081623590,
+-2083339527, -2085033153, -2086704450, -2088353400, -2089979985,
+-2091584189, -2093165993, -2094725382, -2096262337, -2097776843,
+-2099268884, -2100738443, -2102185505, -2103610054, -2105012075,
+-2106391553, -2107748474, -2109082822, -2110394584, -2111683744,
+-2112950291, -2114194210, -2115415487, -2116614110, -2117790065,
+-2118943341, -2120073924, -2121181804, -2122266967, -2123329402,
+-2124369098, -2125386044, -2126380229, -2127351642, -2128300272,
+-2129226111, -2130129147, -2131009371, -2131866773, -2132701345,
+-2133513078, -2134301962, -2135067990, -2135811153, -2136531442,
+-2137228852, -2137903373, -2138555000, -2139183723, -2139789539,
+-2140372438, -2140932416, -2141469466, -2141983583, -2142474761,
+-2142942995, -2143388280, -2143810610, -2144209982, -2144586392,
+-2144939834, -2145270306, -2145577804, -2145862324, -2146123864,
+-2146362421, -2146577992, -2146770575, -2146940167, -2147086768,
+-2147210375, -2147310987, -2147388603, -2147443222, -2147474844,
+2147482929, 2147425435, 2147275952, 2147034487, 2146701050,
+2146275656, 2145758322, 2145149071, 2144447929, 2143654926,
+2142770096, 2141793477, 2140725111, 2139565043, 2138313323,
+2136970005, 2135535146, 2134008809, 2132391057, 2130681961,
+2128881593, 2126990031, 2125007356, 2122933653, 2120769010,
+2118513521, 2116167282, 2113730393, 2111202959, 2108585087,
+2105876892, 2103078487, 2100189994, 2097211535, 2094143239,
+2090985237, 2087737664, 2084400659, 2080974365, 2077458929,
+2073854502, 2070161238, 2066379295, 2062508835, 2058550025,
+2054503033, 2050368032, 2046145201, 2041834720, 2037436773,
+2032951550, 2028379241, 2023720043, 2018974156, 2014141783,
+2009223131, 2004218410, 1999127836, 1993951625, 1988690000,
+1983343186, 1977911412, 1972394912, 1966793920, 1961108677,
+1955339428, 1949486417, 1943549898, 1937530123, 1931427351,
+1925241843, 1918973864, 1912623682, 1906191570, 1899677803,
+1893082661, 1886406424, 1879649381, 1872811820, 1865894033,
+1858896318, 1851818974, 1844662304, 1837426615, 1830112217,
+1822719423, 1815248550, 1807699917, 1800073849, 1792370671,
+1784590714, 1776734311, 1768801799, 1760793518, 1752709809,
+1744551021, 1736317502, 1728009604, 1719627685, 1711172102,
+1702643219, 1694041400, 1685367013, 1676620432, 1667802029,
+1658912184, 1649951276, 1640919689, 1631817811, 1622646032,
+1613404744, 1604094343, 1594715227, 1585267800, 1575752465,
+1566169630, 1556519705, 1546803104, 1537020244, 1527171542,
+1517257422, 1507278307, 1497234626, 1487126808, 1476955286,
+1466720497, 1456422878, 1446062871, 1435640919, 1425157469,
+1414612971, 1404007875, 1393342636, 1382617710, 1371833558,
+1360990642, 1350089425, 1339130374, 1328113960, 1317040654,
+1305910930, 1294725265, 1283484138, 1272188032, 1260837429,
+1249432816, 1237974681, 1226463516, 1214899813, 1203284068,
+1191616778, 1179898443, 1168129565, 1156310649, 1144442200,
+1132524727, 1120558740, 1108544752, 1096483278, 1084374834,
+1072219940, 1060019115, 1047772882, 1035481766, 1023146293,
+1010766993, 998344394, 985879030, 973371434, 960822142,
+948231691, 935600622, 922929474, 910218791, 897469118,
+884680999, 871854984, 858991622, 846091463, 833155061,
+820182969, 807175743, 794133941, 781058120, 767948841,
+754806666, 741632158, 728425880, 715188400, 701920283,
+688622098, 675294414, 661937804, 648552838, 635140090,
+621700135, 608233549, 594740907, 581222789, 567679774,
+554112440, 540521371, 526907147, 513270353, 499611571,
+485931388, 472230390, 458509162, 444768294, 431008373,
+417229989, 403433732, 389620194, 375789965, 361943639,
+348081809, 334205068, 320314011, 306409232, 292491328,
+278560894, 264618528, 250664827, 236700388, 222725809,
+208741690, 194748629, 180747225, 166738079, 152721790,
+138698959, 124670187, 110636075, 96597223, 82554233,
+68507707, 54458246, 40406452, 26352928, 12298274,
+-1756906, -15812011, -29866438, -43919586, -57970853,
+-72019637, -86065335, -100107347, -114145071, -128177904,
+-142205248, -156226499, -170241059, -184248325, -198247699,
+-212238581, -226220372, -240192472, -254154282, -268105206,
+-282044645, -295972002, -309886680, -323788084, -337675619,
+-351548688, -365406698, -379249055, -393075166, -406884440,
+-420676284, -434450107, -448205320, -461941333, -475657559,
+-489353409, -503028296, -516681636, -530312842, -543921332,
+-557506522, -571067830, -584604676, -598116479, -611602660,
+-625062643, -638495850, -651901706, -665279637, -678629069,
+-691949432, -705240153, -718500664, -731730397, -744928785,
+-758095263, -771229267, -784330234, -797397602, -810430813,
+-823429308, -836392529, -849319923, -862210934, -875065011,
+-887881603, -900660162, -913400139, -926100989, -938762167,
+-951383133, -963963344, -976502263, -988999351, -1001454074,
+-1013865898, -1026234291, -1038558724, -1050838668, -1063073598,
+-1075262990, -1087406320, -1099503070, -1111552721, -1123554757,
+-1135508663, -1147413928, -1159270041, -1171076495, -1182832785,
+-1194538405, -1206192856, -1217795637, -1229346252, -1240844206,
+-1252289006, -1263680162, -1275017186, -1286299593, -1297526899,
+-1308698624, -1319814288, -1330873416, -1341875533, -1352820169,
+-1363706855, -1374535124, -1385304512, -1396014559, -1406664805,
+-1417254794, -1427784073, -1438252190, -1448658697, -1459003149,
+-1469285102, -1479504115, -1489659751, -1499751576, -1509779156,
+-1519742062, -1529639867, -1539472148, -1549238483, -1558938453,
+-1568571644, -1578137643, -1587636039, -1597066426, -1606428400,
+-1615721561, -1624945509, -1634099849, -1643184191, -1652198144,
+-1661141322, -1670013342, -1678813825, -1687542393, -1696198672,
+-1704782292, -1713292884, -1721730085, -1730093532, -1738382868,
+-1746597738, -1754737789, -1762802673, -1770792044, -1778705561,
+-1786542883, -1794303676, -1801987607, -1809594347, -1817123570,
+-1824574954, -1831948179, -1839242929, -1846458892, -1853595759,
+-1860653224, -1867630985, -1874528743, -1881346202, -1888083070,
+-1894739060, -1901313885, -1907807264, -1914218919, -1920548575,
+-1926795962, -1932960811, -1939042858, -1945041843, -1950957509,
+-1956789602, -1962537873, -1968202076, -1973781967, -1979277308,
+-1984687864, -1990013401, -1995253694, -2000408516, -2005477648,
+-2010460871, -2015357973, -2020168744, -2024892978, -2029530472,
+-2034081027, -2038544449, -2042920547, -2047209133, -2051410023,
+-2055523038, -2059548001, -2063484740, -2067333086, -2071092874,
+-2074763944, -2078346137, -2081839301, -2085243286, -2088557947,
+-2091783140, -2094918728, -2097964577, -2100920556, -2103786539,
+-2106562402, -2109248028, -2111843300, -2114348108, -2116762344,
+-2119085905, -2121318692, -2123460608, -2125511562, -2127471467,
+-2129340237, -2131117794, -2132804061, -2134398966, -2135902440,
+-2137314419, -2138634843, -2139863654, -2141000801, -2142046235,
+-2142999911, -2143861787, -2144631828, -2145310000, -2145896274,
+-2146390624, -2146793031, -2147103476, -2147321946, -2147448433,
+2147480773, 2147250799, 2146652904, 2145687192, 2144353827,
+2142653038, 2140585116, 2138150417, 2135349356, 2132182414,
+2128650133, 2124753120, 2120492040, 2115867626, 2110880668,
+2105532022, 2099822604, 2093753392, 2087325426, 2080539807,
+2073397699, 2065900325, 2058048970, 2049844978, 2041289756,
+2032384769, 2023131544, 2013531666, 2003586779, 1993298588,
+1982668856, 1971699403, 1960392110, 1948748914, 1936771810,
+1924462850, 1911824143, 1898857855, 1885566207, 1871951478,
+1858015999, 1843762158, 1829192399, 1814309216, 1799115162,
+1783612838, 1767804901, 1751694060, 1735283075, 1718574758,
+1701571972, 1684277631, 1666694698, 1648826185, 1630675154,
+1612244715, 1593538026, 1574558293, 1555308768, 1535792748,
+1516013578, 1495974647, 1475679389, 1455131280, 1434333842,
+1413290638, 1392005275, 1370481398, 1348722696, 1326732898,
+1304515771, 1282075122, 1259414796, 1236538675, 1213450681,
+1190154767, 1166654927, 1142955186, 1119059606, 1094972281,
+1070697338, 1046238936, 1021601267, 996788551, 971805042,
+946655018, 921342790, 895872694, 870249095, 844476384,
+818558976, 792501312, 766307857, 739983099, 713531549,
+686957739, 660266222, 633461572, 606548381, 579531262,
+552414843, 525203770, 497902707, 470516330, 443049333,
+415506422, 387892316, 360211746, 332469456, 304670200,
+276818739, 248919847, 220978304, 192998897, 164986421,
+136945676, 108881465, 80798598, 52701887, 24596146,
+-3513810, -31623164, -59727099, -87820801, -115899455,
+-143958250, -171992378, -199997036, -227967426, -255898755,
+-283786237, -311625094, -339410555, -367137861, -394802258,
+-422399009, -449923384, -477370666, -504736154, -532015158,
+-559203003, -586295032, -613286603, -640173090, -666949886,
+-693612404, -720156076, -746576352, -772868706, -799028633,
+-825051651, -850933300, -876669146, -902254780, -927685817,
+-952957899, -978066697, -1003007909, -1027777260, -1052370507,
+-1076783436, -1101011863, -1125051638, -1148898640, -1172548785,
+-1195998020, -1219242327, -1242277723, -1265100260, -1287706030,
+-1310091157, -1332251808, -1354184184, -1375884527, -1397349119,
+-1418574283, -1439556382, -1460291820, -1480777044, -1501008545,
+-1520982856, -1540696555, -1560146263, -1579328647, -1598240423,
+-1616878347, -1635239228, -1653319919, -1671117323, -1688628389,
+-1705850117, -1722779556, -1739413807, -1755750017, -1771785389,
+-1787517174, -1802942678, -1818059257, -1832864320, -1847355332,
+-1861529809, -1875385322, -1888919498, -1902130017, -1915014616,
+-1927571087, -1939797279, -1951691096, -1963250501, -1974473513,
+-1985358210, -1995902725, -2006105253, -2015964045, -2025477412,
+-2034643724, -2043461410, -2051928960, -2060044922, -2067807906,
+-2075216581, -2082269679, -2088965991, -2095304370, -2101283728,
+-2106903043, -2112161350, -2117057750, -2121591402, -2125761531,
+-2129567422, -2133008422, -2136083942, -2138793455, -2141136497,
+-2143112666, -2144721624, -2145963095, -2146836866, -2147342788,
+#else
+32767, 32767, 32767, 32767, 32767,
+32767, 32766, 32766, 32765, 32764,
+32764, 32763, 32762, 32760, 32759,
+32758, 32757, 32755, 32754, 32752,
+32750, 32748, 32747, 32745, 32742,
+32740, 32738, 32736, 32733, 32731,
+32728, 32726, 32723, 32720, 32717,
+32714, 32711, 32708, 32704, 32701,
+32697, 32694, 32690, 32686, 32683,
+32679, 32675, 32671, 32666, 32662,
+32658, 32653, 32649, 32644, 32640,
+32635, 32630, 32625, 32620, 32615,
+32610, 32604, 32599, 32593, 32588,
+32582, 32576, 32571, 32565, 32559,
+32553, 32546, 32540, 32534, 32527,
+32521, 32514, 32507, 32501, 32494,
+32487, 32480, 32473, 32465, 32458,
+32451, 32443, 32436, 32428, 32420,
+32412, 32404, 32396, 32388, 32380,
+32372, 32364, 32355, 32347, 32338,
+32329, 32320, 32312, 32303, 32294,
+32284, 32275, 32266, 32257, 32247,
+32237, 32228, 32218, 32208, 32198,
+32188, 32178, 32168, 32158, 32147,
+32137, 32127, 32116, 32105, 32094,
+32084, 32073, 32062, 32051, 32039,
+32028, 32017, 32005, 31994, 31982,
+31970, 31959, 31947, 31935, 31923,
+31910, 31898, 31886, 31874, 31861,
+31848, 31836, 31823, 31810, 31797,
+31784, 31771, 31758, 31745, 31732,
+31718, 31705, 31691, 31677, 31664,
+31650, 31636, 31622, 31608, 31593,
+31579, 31565, 31550, 31536, 31521,
+31507, 31492, 31477, 31462, 31447,
+31432, 31417, 31401, 31386, 31371,
+31355, 31339, 31324, 31308, 31292,
+31276, 31260, 31244, 31228, 31212,
+31195, 31179, 31162, 31146, 31129,
+31112, 31095, 31078, 31061, 31044,
+31027, 31010, 30992, 30975, 30957,
+30940, 30922, 30904, 30886, 30868,
+30850, 30832, 30814, 30796, 30777,
+30759, 30740, 30722, 30703, 30684,
+30665, 30646, 30627, 30608, 30589,
+30570, 30551, 30531, 30512, 30492,
+30472, 30453, 30433, 30413, 30393,
+30373, 30353, 30332, 30312, 30292,
+30271, 30251, 30230, 30209, 30188,
+30167, 30146, 30125, 30104, 30083,
+30062, 30040, 30019, 29997, 29976,
+29954, 29932, 29910, 29889, 29867,
+29844, 29822, 29800, 29778, 29755,
+29733, 29710, 29687, 29665, 29642,
+29619, 29596, 29573, 29550, 29527,
+29503, 29480, 29457, 29433, 29409,
+29386, 29362, 29338, 29314, 29290,
+29266, 29242, 29218, 29193, 29169,
+29145, 29120, 29095, 29071, 29046,
+29021, 28996, 28971, 28946, 28921,
+28896, 28870, 28845, 28819, 28794,
+28768, 28743, 28717, 28691, 28665,
+28639, 28613, 28587, 28560, 28534,
+28508, 28481, 28455, 28428, 28401,
+28375, 28348, 28321, 28294, 28267,
+28240, 28212, 28185, 28158, 28130,
+28103, 28075, 28047, 28020, 27992,
+27964, 27936, 27908, 27880, 27851,
+27823, 27795, 27766, 27738, 27709,
+27681, 27652, 27623, 27594, 27565,
+27536, 27507, 27478, 27449, 27419,
+27390, 27360, 27331, 27301, 27272,
+27242, 27212, 27182, 27152, 27122,
+27092, 27062, 27032, 27001, 26971,
+26940, 26910, 26879, 26848, 26818,
+26787, 26756, 26725, 26694, 26663,
+26631, 26600, 26569, 26537, 26506,
+26474, 26443, 26411, 26379, 26347,
+26316, 26284, 26251, 26219, 26187,
+26155, 26123, 26090, 26058, 26025,
+25993, 25960, 25927, 25894, 25861,
+25828, 25795, 25762, 25729, 25696,
+25663, 25629, 25596, 25562, 25529,
+25495, 25461, 25428, 25394, 25360,
+25326, 25292, 25258, 25223, 25189,
+25155, 25120, 25086, 25051, 25017,
+24982, 24947, 24913, 24878, 24843,
+24808, 24773, 24738, 24702, 24667,
+24632, 24596, 24561, 24525, 24490,
+24454, 24419, 24383, 24347, 24311,
+24275, 24239, 24203, 24167, 24130,
+24094, 24058, 24021, 23985, 23948,
+23912, 23875, 23838, 23801, 23764,
+23728, 23690, 23653, 23616, 23579,
+23542, 23504, 23467, 23430, 23392,
+23355, 23317, 23279, 23241, 23204,
+23166, 23128, 23090, 23052, 23014,
+22975, 22937, 22899, 22860, 22822,
+22783, 22745, 22706, 22668, 22629,
+22590, 22551, 22512, 22473, 22434,
+22395, 22356, 22317, 22277, 22238,
+22199, 22159, 22120, 22080, 22040,
+22001, 21961, 21921, 21881, 21841,
+21801, 21761, 21721, 21681, 21641,
+21600, 21560, 21520, 21479, 21439,
+21398, 21357, 21317, 21276, 21235,
+21194, 21153, 21112, 21071, 21030,
+20989, 20948, 20907, 20865, 20824,
+20783, 20741, 20700, 20658, 20616,
+20575, 20533, 20491, 20449, 20407,
+20365, 20323, 20281, 20239, 20197,
+20155, 20112, 20070, 20028, 19985,
+19943, 19900, 19857, 19815, 19772,
+19729, 19686, 19643, 19601, 19558,
+19514, 19471, 19428, 19385, 19342,
+19298, 19255, 19212, 19168, 19125,
+19081, 19038, 18994, 18950, 18906,
+18863, 18819, 18775, 18731, 18687,
+18643, 18599, 18554, 18510, 18466,
+18422, 18377, 18333, 18288, 18244,
+18199, 18155, 18110, 18065, 18021,
+17976, 17931, 17886, 17841, 17796,
+17751, 17706, 17661, 17616, 17570,
+17525, 17480, 17434, 17389, 17344,
+17298, 17252, 17207, 17161, 17116,
+17070, 17024, 16978, 16932, 16886,
+16840, 16794, 16748, 16702, 16656,
+16610, 16564, 16517, 16471, 16425,
+16378, 16332, 16285, 16239, 16192,
+16145, 16099, 16052, 16005, 15958,
+15912, 15865, 15818, 15771, 15724,
+15677, 15630, 15583, 15535, 15488,
+15441, 15394, 15346, 15299, 15251,
+15204, 15156, 15109, 15061, 15014,
+14966, 14918, 14870, 14823, 14775,
+14727, 14679, 14631, 14583, 14535,
+14487, 14439, 14391, 14342, 14294,
+14246, 14198, 14149, 14101, 14053,
+14004, 13956, 13907, 13858, 13810,
+13761, 13713, 13664, 13615, 13566,
+13517, 13469, 13420, 13371, 13322,
+13273, 13224, 13175, 13126, 13076,
+13027, 12978, 12929, 12880, 12830,
+12781, 12731, 12682, 12633, 12583,
+12534, 12484, 12434, 12385, 12335,
+12285, 12236, 12186, 12136, 12086,
+12037, 11987, 11937, 11887, 11837,
+11787, 11737, 11687, 11637, 11586,
+11536, 11486, 11436, 11386, 11335,
+11285, 11235, 11184, 11134, 11083,
+11033, 10982, 10932, 10881, 10831,
+10780, 10729, 10679, 10628, 10577,
+10527, 10476, 10425, 10374, 10323,
+10272, 10221, 10170, 10119, 10068,
+10017, 9966, 9915, 9864, 9813,
+9762, 9711, 9659, 9608, 9557,
+9506, 9454, 9403, 9352, 9300,
+9249, 9197, 9146, 9094, 9043,
+8991, 8940, 8888, 8836, 8785,
+8733, 8681, 8630, 8578, 8526,
+8475, 8423, 8371, 8319, 8267,
+8215, 8163, 8111, 8059, 8007,
+7955, 7903, 7851, 7799, 7747,
+7695, 7643, 7591, 7539, 7487,
+7434, 7382, 7330, 7278, 7225,
+7173, 7121, 7068, 7016, 6964,
+6911, 6859, 6806, 6754, 6701,
+6649, 6596, 6544, 6491, 6439,
+6386, 6334, 6281, 6228, 6176,
+6123, 6070, 6018, 5965, 5912,
+5859, 5807, 5754, 5701, 5648,
+5595, 5543, 5490, 5437, 5384,
+5331, 5278, 5225, 5172, 5119,
+5066, 5013, 4960, 4907, 4854,
+4801, 4748, 4695, 4642, 4589,
+4536, 4483, 4430, 4377, 4324,
+4270, 4217, 4164, 4111, 4058,
+4005, 3951, 3898, 3845, 3792,
+3738, 3685, 3632, 3578, 3525,
+3472, 3419, 3365, 3312, 3259,
+3205, 3152, 3098, 3045, 2992,
+2938, 2885, 2831, 2778, 2725,
+2671, 2618, 2564, 2511, 2457,
+2404, 2350, 2297, 2243, 2190,
+2136, 2083, 2029, 1976, 1922,
+1869, 1815, 1762, 1708, 1655,
+1601, 1548, 1494, 1440, 1387,
+1333, 1280, 1226, 1173, 1119,
+1065, 1012, 958, 905, 851,
+797, 744, 690, 637, 583,
+529, 476, 422, 369, 315,
+261, 208, 154, 101, 47,
+-7, -60, -114, -168, -221,
+-275, -328, -382, -436, -489,
+-543, -596, -650, -704, -757,
+-811, -864, -918, -972, -1025,
+-1079, -1132, -1186, -1240, -1293,
+-1347, -1400, -1454, -1507, -1561,
+-1615, -1668, -1722, -1775, -1829,
+-1882, -1936, -1989, -2043, -2096,
+-2150, -2203, -2257, -2310, -2364,
+-2417, -2471, -2524, -2578, -2631,
+-2685, -2738, -2791, -2845, -2898,
+-2952, -3005, -3058, -3112, -3165,
+-3218, -3272, -3325, -3379, -3432,
+-3485, -3538, -3592, -3645, -3698,
+-3752, -3805, -3858, -3911, -3965,
+-4018, -4071, -4124, -4177, -4231,
+-4284, -4337, -4390, -4443, -4496,
+-4549, -4602, -4656, -4709, -4762,
+-4815, -4868, -4921, -4974, -5027,
+-5080, -5133, -5186, -5239, -5291,
+-5344, -5397, -5450, -5503, -5556,
+-5609, -5662, -5714, -5767, -5820,
+-5873, -5925, -5978, -6031, -6083,
+-6136, -6189, -6241, -6294, -6347,
+-6399, -6452, -6504, -6557, -6609,
+-6662, -6714, -6767, -6819, -6872,
+-6924, -6977, -7029, -7081, -7134,
+-7186, -7238, -7291, -7343, -7395,
+-7447, -7500, -7552, -7604, -7656,
+-7708, -7760, -7812, -7864, -7916,
+-7968, -8020, -8072, -8124, -8176,
+-8228, -8280, -8332, -8384, -8436,
+-8487, -8539, -8591, -8643, -8694,
+-8746, -8798, -8849, -8901, -8953,
+-9004, -9056, -9107, -9159, -9210,
+-9262, -9313, -9364, -9416, -9467,
+-9518, -9570, -9621, -9672, -9723,
+-9775, -9826, -9877, -9928, -9979,
+-10030, -10081, -10132, -10183, -10234,
+-10285, -10336, -10387, -10438, -10488,
+-10539, -10590, -10641, -10691, -10742,
+-10793, -10843, -10894, -10945, -10995,
+-11046, -11096, -11146, -11197, -11247,
+-11298, -11348, -11398, -11448, -11499,
+-11549, -11599, -11649, -11699, -11749,
+-11799, -11849, -11899, -11949, -11999,
+-12049, -12099, -12149, -12198, -12248,
+-12298, -12348, -12397, -12447, -12496,
+-12546, -12595, -12645, -12694, -12744,
+-12793, -12843, -12892, -12941, -12990,
+-13040, -13089, -13138, -13187, -13236,
+-13285, -13334, -13383, -13432, -13481,
+-13530, -13579, -13627, -13676, -13725,
+-13773, -13822, -13871, -13919, -13968,
+-14016, -14065, -14113, -14161, -14210,
+-14258, -14306, -14355, -14403, -14451,
+-14499, -14547, -14595, -14643, -14691,
+-14739, -14787, -14835, -14882, -14930,
+-14978, -15025, -15073, -15121, -15168,
+-15216, -15263, -15311, -15358, -15405,
+-15453, -15500, -15547, -15594, -15641,
+-15689, -15736, -15783, -15830, -15876,
+-15923, -15970, -16017, -16064, -16110,
+-16157, -16204, -16250, -16297, -16343,
+-16390, -16436, -16483, -16529, -16575,
+-16621, -16668, -16714, -16760, -16806,
+-16852, -16898, -16944, -16990, -17035,
+-17081, -17127, -17173, -17218, -17264,
+-17309, -17355, -17400, -17446, -17491,
+-17536, -17582, -17627, -17672, -17717,
+-17762, -17807, -17852, -17897, -17942,
+-17987, -18032, -18077, -18121, -18166,
+-18210, -18255, -18300, -18344, -18388,
+-18433, -18477, -18521, -18566, -18610,
+-18654, -18698, -18742, -18786, -18830,
+-18874, -18917, -18961, -19005, -19048,
+-19092, -19136, -19179, -19223, -19266,
+-19309, -19353, -19396, -19439, -19482,
+-19525, -19568, -19611, -19654, -19697,
+-19740, -19783, -19825, -19868, -19911,
+-19953, -19996, -20038, -20081, -20123,
+-20165, -20207, -20250, -20292, -20334,
+-20376, -20418, -20460, -20502, -20543,
+-20585, -20627, -20668, -20710, -20752,
+-20793, -20834, -20876, -20917, -20958,
+-20999, -21041, -21082, -21123, -21164,
+-21205, -21245, -21286, -21327, -21368,
+-21408, -21449, -21489, -21530, -21570,
+-21610, -21651, -21691, -21731, -21771,
+-21811, -21851, -21891, -21931, -21971,
+-22011, -22050, -22090, -22130, -22169,
+-22208, -22248, -22287, -22326, -22366,
+-22405, -22444, -22483, -22522, -22561,
+-22600, -22639, -22677, -22716, -22755,
+-22793, -22832, -22870, -22908, -22947,
+-22985, -23023, -23061, -23099, -23137,
+-23175, -23213, -23251, -23289, -23326,
+-23364, -23402, -23439, -23476, -23514,
+-23551, -23588, -23626, -23663, -23700,
+-23737, -23774, -23811, -23847, -23884,
+-23921, -23957, -23994, -24030, -24067,
+-24103, -24139, -24176, -24212, -24248,
+-24284, -24320, -24356, -24392, -24427,
+-24463, -24499, -24534, -24570, -24605,
+-24641, -24676, -24711, -24746, -24782,
+-24817, -24852, -24886, -24921, -24956,
+-24991, -25025, -25060, -25095, -25129,
+-25163, -25198, -25232, -25266, -25300,
+-25334, -25368, -25402, -25436, -25470,
+-25503, -25537, -25571, -25604, -25638,
+-25671, -25704, -25737, -25771, -25804,
+-25837, -25870, -25902, -25935, -25968,
+-26001, -26033, -26066, -26098, -26131,
+-26163, -26195, -26227, -26259, -26292,
+-26323, -26355, -26387, -26419, -26451,
+-26482, -26514, -26545, -26577, -26608,
+-26639, -26670, -26702, -26733, -26764,
+-26794, -26825, -26856, -26887, -26917,
+-26948, -26978, -27009, -27039, -27069,
+-27100, -27130, -27160, -27190, -27220,
+-27249, -27279, -27309, -27338, -27368,
+-27397, -27427, -27456, -27485, -27514,
+-27543, -27572, -27601, -27630, -27659,
+-27688, -27716, -27745, -27773, -27802,
+-27830, -27858, -27887, -27915, -27943,
+-27971, -27999, -28026, -28054, -28082,
+-28109, -28137, -28164, -28192, -28219,
+-28246, -28273, -28301, -28328, -28354,
+-28381, -28408, -28435, -28461, -28488,
+-28514, -28541, -28567, -28593, -28619,
+-28645, -28671, -28697, -28723, -28749,
+-28775, -28800, -28826, -28851, -28877,
+-28902, -28927, -28952, -28977, -29002,
+-29027, -29052, -29077, -29102, -29126,
+-29151, -29175, -29200, -29224, -29248,
+-29272, -29296, -29320, -29344, -29368,
+-29392, -29415, -29439, -29462, -29486,
+-29509, -29532, -29556, -29579, -29602,
+-29625, -29648, -29670, -29693, -29716,
+-29738, -29761, -29783, -29806, -29828,
+-29850, -29872, -29894, -29916, -29938,
+-29960, -29981, -30003, -30024, -30046,
+-30067, -30088, -30110, -30131, -30152,
+-30173, -30194, -30214, -30235, -30256,
+-30276, -30297, -30317, -30337, -30358,
+-30378, -30398, -30418, -30438, -30458,
+-30477, -30497, -30516, -30536, -30555,
+-30575, -30594, -30613, -30632, -30651,
+-30670, -30689, -30708, -30726, -30745,
+-30763, -30782, -30800, -30819, -30837,
+-30855, -30873, -30891, -30909, -30926,
+-30944, -30962, -30979, -30997, -31014,
+-31031, -31048, -31065, -31082, -31099,
+-31116, -31133, -31150, -31166, -31183,
+-31199, -31216, -31232, -31248, -31264,
+-31280, -31296, -31312, -31328, -31343,
+-31359, -31374, -31390, -31405, -31421,
+-31436, -31451, -31466, -31481, -31496,
+-31510, -31525, -31540, -31554, -31568,
+-31583, -31597, -31611, -31625, -31639,
+-31653, -31667, -31681, -31694, -31708,
+-31721, -31735, -31748, -31761, -31775,
+-31788, -31801, -31813, -31826, -31839,
+-31852, -31864, -31877, -31889, -31901,
+-31914, -31926, -31938, -31950, -31961,
+-31973, -31985, -31997, -32008, -32020,
+-32031, -32042, -32053, -32064, -32075,
+-32086, -32097, -32108, -32119, -32129,
+-32140, -32150, -32160, -32171, -32181,
+-32191, -32201, -32211, -32221, -32230,
+-32240, -32249, -32259, -32268, -32278,
+-32287, -32296, -32305, -32314, -32323,
+-32331, -32340, -32349, -32357, -32366,
+-32374, -32382, -32390, -32398, -32406,
+-32414, -32422, -32430, -32437, -32445,
+-32453, -32460, -32467, -32474, -32482,
+-32489, -32495, -32502, -32509, -32516,
+-32522, -32529, -32535, -32542, -32548,
+-32554, -32560, -32566, -32572, -32578,
+-32584, -32589, -32595, -32600, -32606,
+-32611, -32616, -32621, -32626, -32631,
+-32636, -32641, -32645, -32650, -32655,
+-32659, -32663, -32668, -32672, -32676,
+-32680, -32684, -32687, -32691, -32695,
+-32698, -32702, -32705, -32708, -32712,
+-32715, -32718, -32721, -32723, -32726,
+-32729, -32731, -32734, -32736, -32739,
+-32741, -32743, -32745, -32747, -32749,
+-32751, -32752, -32754, -32756, -32757,
+-32758, -32760, -32761, -32762, -32763,
+-32764, -32765, -32765, -32766, -32766,
+-32767, -32767, -32767, -32767, -32767,
+32767, 32767, 32767, 32766, 32765,
+32763, 32761, 32759, 32756, 32753,
+32750, 32746, 32742, 32738, 32733,
+32728, 32722, 32717, 32710, 32704,
+32697, 32690, 32682, 32674, 32666,
+32657, 32648, 32639, 32629, 32619,
+32609, 32598, 32587, 32576, 32564,
+32552, 32539, 32526, 32513, 32500,
+32486, 32472, 32457, 32442, 32427,
+32411, 32395, 32379, 32362, 32345,
+32328, 32310, 32292, 32274, 32255,
+32236, 32217, 32197, 32177, 32157,
+32136, 32115, 32093, 32071, 32049,
+32027, 32004, 31981, 31957, 31933,
+31909, 31884, 31859, 31834, 31809,
+31783, 31756, 31730, 31703, 31676,
+31648, 31620, 31592, 31563, 31534,
+31505, 31475, 31445, 31415, 31384,
+31353, 31322, 31290, 31258, 31226,
+31193, 31160, 31127, 31093, 31059,
+31025, 30990, 30955, 30920, 30884,
+30848, 30812, 30775, 30738, 30701,
+30663, 30625, 30587, 30548, 30509,
+30470, 30430, 30390, 30350, 30309,
+30269, 30227, 30186, 30144, 30102,
+30059, 30016, 29973, 29930, 29886,
+29842, 29797, 29752, 29707, 29662,
+29616, 29570, 29524, 29477, 29430,
+29383, 29335, 29287, 29239, 29190,
+29142, 29092, 29043, 28993, 28943,
+28892, 28842, 28791, 28739, 28688,
+28636, 28583, 28531, 28478, 28425,
+28371, 28317, 28263, 28209, 28154,
+28099, 28044, 27988, 27932, 27876,
+27820, 27763, 27706, 27648, 27591,
+27533, 27474, 27416, 27357, 27298,
+27238, 27178, 27118, 27058, 26997,
+26936, 26875, 26814, 26752, 26690,
+26628, 26565, 26502, 26439, 26375,
+26312, 26247, 26183, 26119, 26054,
+25988, 25923, 25857, 25791, 25725,
+25658, 25592, 25524, 25457, 25389,
+25322, 25253, 25185, 25116, 25047,
+24978, 24908, 24838, 24768, 24698,
+24627, 24557, 24485, 24414, 24342,
+24270, 24198, 24126, 24053, 23980,
+23907, 23834, 23760, 23686, 23612,
+23537, 23462, 23387, 23312, 23237,
+23161, 23085, 23009, 22932, 22856,
+22779, 22701, 22624, 22546, 22468,
+22390, 22312, 22233, 22154, 22075,
+21996, 21916, 21836, 21756, 21676,
+21595, 21515, 21434, 21352, 21271,
+21189, 21107, 21025, 20943, 20860,
+20777, 20694, 20611, 20528, 20444,
+20360, 20276, 20192, 20107, 20022,
+19937, 19852, 19767, 19681, 19595,
+19509, 19423, 19336, 19250, 19163,
+19076, 18988, 18901, 18813, 18725,
+18637, 18549, 18460, 18372, 18283,
+18194, 18104, 18015, 17925, 17835,
+17745, 17655, 17565, 17474, 17383,
+17292, 17201, 17110, 17018, 16927,
+16835, 16743, 16650, 16558, 16465,
+16372, 16279, 16186, 16093, 15999,
+15906, 15812, 15718, 15624, 15529,
+15435, 15340, 15245, 15150, 15055,
+14960, 14864, 14769, 14673, 14577,
+14481, 14385, 14288, 14192, 14095,
+13998, 13901, 13804, 13706, 13609,
+13511, 13414, 13316, 13218, 13119,
+13021, 12923, 12824, 12725, 12626,
+12527, 12428, 12329, 12230, 12130,
+12030, 11930, 11831, 11730, 11630,
+11530, 11430, 11329, 11228, 11128,
+11027, 10926, 10824, 10723, 10622,
+10520, 10419, 10317, 10215, 10113,
+10011, 9909, 9807, 9704, 9602,
+9499, 9397, 9294, 9191, 9088,
+8985, 8882, 8778, 8675, 8572,
+8468, 8364, 8261, 8157, 8053,
+7949, 7845, 7741, 7637, 7532,
+7428, 7323, 7219, 7114, 7009,
+6905, 6800, 6695, 6590, 6485,
+6380, 6274, 6169, 6064, 5958,
+5853, 5747, 5642, 5536, 5430,
+5325, 5219, 5113, 5007, 4901,
+4795, 4689, 4583, 4476, 4370,
+4264, 4157, 4051, 3945, 3838,
+3732, 3625, 3518, 3412, 3305,
+3198, 3092, 2985, 2878, 2771,
+2664, 2558, 2451, 2344, 2237,
+2130, 2023, 1916, 1809, 1702,
+1594, 1487, 1380, 1273, 1166,
+1059, 952, 844, 737, 630,
+523, 416, 308, 201, 94,
+-13, -121, -228, -335, -442,
+-550, -657, -764, -871, -978,
+-1086, -1193, -1300, -1407, -1514,
+-1621, -1728, -1835, -1942, -2049,
+-2157, -2263, -2370, -2477, -2584,
+-2691, -2798, -2905, -3012, -3118,
+-3225, -3332, -3439, -3545, -3652,
+-3758, -3865, -3971, -4078, -4184,
+-4290, -4397, -4503, -4609, -4715,
+-4821, -4927, -5033, -5139, -5245,
+-5351, -5457, -5562, -5668, -5774,
+-5879, -5985, -6090, -6195, -6301,
+-6406, -6511, -6616, -6721, -6826,
+-6931, -7036, -7140, -7245, -7349,
+-7454, -7558, -7663, -7767, -7871,
+-7975, -8079, -8183, -8287, -8390,
+-8494, -8597, -8701, -8804, -8907,
+-9011, -9114, -9217, -9319, -9422,
+-9525, -9627, -9730, -9832, -9934,
+-10037, -10139, -10241, -10342, -10444,
+-10546, -10647, -10748, -10850, -10951,
+-11052, -11153, -11253, -11354, -11455,
+-11555, -11655, -11756, -11856, -11955,
+-12055, -12155, -12254, -12354, -12453,
+-12552, -12651, -12750, -12849, -12947,
+-13046, -13144, -13242, -13340, -13438,
+-13536, -13633, -13731, -13828, -13925,
+-14022, -14119, -14216, -14312, -14409,
+-14505, -14601, -14697, -14793, -14888,
+-14984, -15079, -15174, -15269, -15364,
+-15459, -15553, -15647, -15741, -15835,
+-15929, -16023, -16116, -16210, -16303,
+-16396, -16488, -16581, -16673, -16766,
+-16858, -16949, -17041, -17133, -17224,
+-17315, -17406, -17497, -17587, -17678,
+-17768, -17858, -17948, -18037, -18127,
+-18216, -18305, -18394, -18483, -18571,
+-18659, -18747, -18835, -18923, -19010,
+-19098, -19185, -19271, -19358, -19444,
+-19531, -19617, -19702, -19788, -19873,
+-19959, -20043, -20128, -20213, -20297,
+-20381, -20465, -20549, -20632, -20715,
+-20798, -20881, -20963, -21046, -21128,
+-21210, -21291, -21373, -21454, -21535,
+-21616, -21696, -21776, -21856, -21936,
+-22016, -22095, -22174, -22253, -22331,
+-22410, -22488, -22566, -22643, -22721,
+-22798, -22875, -22951, -23028, -23104,
+-23180, -23256, -23331, -23406, -23481,
+-23556, -23630, -23704, -23778, -23852,
+-23925, -23998, -24071, -24144, -24216,
+-24288, -24360, -24432, -24503, -24574,
+-24645, -24716, -24786, -24856, -24926,
+-24995, -25064, -25133, -25202, -25270,
+-25339, -25406, -25474, -25541, -25608,
+-25675, -25742, -25808, -25874, -25939,
+-26005, -26070, -26135, -26199, -26264,
+-26327, -26391, -26455, -26518, -26581,
+-26643, -26705, -26767, -26829, -26891,
+-26952, -27013, -27073, -27133, -27193,
+-27253, -27312, -27372, -27430, -27489,
+-27547, -27605, -27663, -27720, -27777,
+-27834, -27890, -27946, -28002, -28058,
+-28113, -28168, -28223, -28277, -28331,
+-28385, -28438, -28491, -28544, -28596,
+-28649, -28701, -28752, -28803, -28854,
+-28905, -28955, -29006, -29055, -29105,
+-29154, -29203, -29251, -29299, -29347,
+-29395, -29442, -29489, -29535, -29582,
+-29628, -29673, -29719, -29764, -29808,
+-29853, -29897, -29941, -29984, -30027,
+-30070, -30112, -30154, -30196, -30238,
+-30279, -30320, -30360, -30400, -30440,
+-30480, -30519, -30558, -30596, -30635,
+-30672, -30710, -30747, -30784, -30821,
+-30857, -30893, -30929, -30964, -30999,
+-31033, -31068, -31102, -31135, -31168,
+-31201, -31234, -31266, -31298, -31330,
+-31361, -31392, -31422, -31453, -31483,
+-31512, -31541, -31570, -31599, -31627,
+-31655, -31682, -31710, -31737, -31763,
+-31789, -31815, -31841, -31866, -31891,
+-31915, -31939, -31963, -31986, -32010,
+-32032, -32055, -32077, -32099, -32120,
+-32141, -32162, -32182, -32202, -32222,
+-32241, -32260, -32279, -32297, -32315,
+-32333, -32350, -32367, -32383, -32399,
+-32415, -32431, -32446, -32461, -32475,
+-32489, -32503, -32517, -32530, -32542,
+-32555, -32567, -32579, -32590, -32601,
+-32612, -32622, -32632, -32641, -32651,
+-32659, -32668, -32676, -32684, -32692,
+-32699, -32706, -32712, -32718, -32724,
+-32729, -32734, -32739, -32743, -32747,
+-32751, -32754, -32757, -32760, -32762,
+-32764, -32765, -32767, -32767, -32767,
+32767, 32767, 32765, 32761, 32756,
+32750, 32742, 32732, 32722, 32710,
+32696, 32681, 32665, 32647, 32628,
+32608, 32586, 32562, 32538, 32512,
+32484, 32455, 32425, 32393, 32360,
+32326, 32290, 32253, 32214, 32174,
+32133, 32090, 32046, 32001, 31954,
+31906, 31856, 31805, 31753, 31700,
+31645, 31588, 31530, 31471, 31411,
+31349, 31286, 31222, 31156, 31089,
+31020, 30951, 30880, 30807, 30733,
+30658, 30582, 30504, 30425, 30345,
+30263, 30181, 30096, 30011, 29924,
+29836, 29747, 29656, 29564, 29471,
+29377, 29281, 29184, 29086, 28987,
+28886, 28784, 28681, 28577, 28471,
+28365, 28257, 28147, 28037, 27925,
+27812, 27698, 27583, 27467, 27349,
+27231, 27111, 26990, 26868, 26744,
+26620, 26494, 26367, 26239, 26110,
+25980, 25849, 25717, 25583, 25449,
+25313, 25176, 25038, 24900, 24760,
+24619, 24477, 24333, 24189, 24044,
+23898, 23751, 23602, 23453, 23303,
+23152, 22999, 22846, 22692, 22537,
+22380, 22223, 22065, 21906, 21746,
+21585, 21423, 21261, 21097, 20933,
+20767, 20601, 20434, 20265, 20096,
+19927, 19756, 19584, 19412, 19239,
+19065, 18890, 18714, 18538, 18361,
+18183, 18004, 17824, 17644, 17463,
+17281, 17098, 16915, 16731, 16546,
+16361, 16175, 15988, 15800, 15612,
+15423, 15234, 15043, 14852, 14661,
+14469, 14276, 14083, 13889, 13694,
+13499, 13303, 13107, 12910, 12713,
+12515, 12317, 12118, 11918, 11718,
+11517, 11316, 11115, 10913, 10710,
+10508, 10304, 10100, 9896, 9691,
+9486, 9281, 9075, 8869, 8662,
+8455, 8248, 8040, 7832, 7623,
+7415, 7206, 6996, 6787, 6577,
+6366, 6156, 5945, 5734, 5523,
+5311, 5100, 4888, 4675, 4463,
+4251, 4038, 3825, 3612, 3399,
+3185, 2972, 2758, 2544, 2330,
+2116, 1902, 1688, 1474, 1260,
+1045, 831, 617, 402, 188,
+-27, -241, -456, -670, -885,
+-1099, -1313, -1528, -1742, -1956,
+-2170, -2384, -2598, -2811, -3025,
+-3239, -3452, -3665, -3878, -4091,
+-4304, -4516, -4728, -4941, -5153,
+-5364, -5576, -5787, -5998, -6209,
+-6419, -6629, -6839, -7049, -7258,
+-7467, -7676, -7884, -8092, -8300,
+-8507, -8714, -8920, -9127, -9332,
+-9538, -9743, -9947, -10151, -10355,
+-10558, -10761, -10963, -11165, -11367,
+-11568, -11768, -11968, -12167, -12366,
+-12565, -12762, -12960, -13156, -13352,
+-13548, -13743, -13937, -14131, -14324,
+-14517, -14709, -14900, -15091, -15281,
+-15470, -15659, -15847, -16035, -16221,
+-16407, -16593, -16777, -16961, -17144,
+-17326, -17508, -17689, -17869, -18049,
+-18227, -18405, -18582, -18758, -18934,
+-19108, -19282, -19455, -19627, -19799,
+-19969, -20139, -20308, -20475, -20642,
+-20809, -20974, -21138, -21301, -21464,
+-21626, -21786, -21946, -22105, -22263,
+-22420, -22575, -22730, -22884, -23037,
+-23189, -23340, -23490, -23640, -23788,
+-23935, -24080, -24225, -24369, -24512,
+-24654, -24795, -24934, -25073, -25211,
+-25347, -25482, -25617, -25750, -25882,
+-26013, -26143, -26272, -26399, -26526,
+-26651, -26775, -26898, -27020, -27141,
+-27260, -27379, -27496, -27612, -27727,
+-27841, -27953, -28065, -28175, -28284,
+-28391, -28498, -28603, -28707, -28810,
+-28911, -29012, -29111, -29209, -29305,
+-29401, -29495, -29587, -29679, -29769,
+-29858, -29946, -30032, -30118, -30201,
+-30284, -30365, -30445, -30524, -30601,
+-30677, -30752, -30825, -30897, -30968,
+-31038, -31106, -31172, -31238, -31302,
+-31365, -31426, -31486, -31545, -31602,
+-31658, -31713, -31766, -31818, -31869,
+-31918, -31966, -32012, -32058, -32101,
+-32144, -32185, -32224, -32262, -32299,
+-32335, -32369, -32401, -32433, -32463,
+-32491, -32518, -32544, -32568, -32591,
+-32613, -32633, -32652, -32669, -32685,
+-32700, -32713, -32724, -32735, -32744,
+-32751, -32757, -32762, -32766, -32767,
+32767, 32764, 32755, 32741, 32720,
+32694, 32663, 32626, 32583, 32535,
+32481, 32421, 32356, 32286, 32209,
+32128, 32041, 31948, 31850, 31747,
+31638, 31523, 31403, 31278, 31148,
+31012, 30871, 30724, 30572, 30415,
+30253, 30086, 29913, 29736, 29553,
+29365, 29172, 28974, 28771, 28564,
+28351, 28134, 27911, 27684, 27452,
+27216, 26975, 26729, 26478, 26223,
+25964, 25700, 25432, 25159, 24882,
+24601, 24315, 24026, 23732, 23434,
+23133, 22827, 22517, 22204, 21886,
+21565, 21240, 20912, 20580, 20244,
+19905, 19563, 19217, 18868, 18516,
+18160, 17802, 17440, 17075, 16708,
+16338, 15964, 15588, 15210, 14829,
+14445, 14059, 13670, 13279, 12886,
+12490, 12093, 11693, 11291, 10888,
+10482, 10075, 9666, 9255, 8843,
+8429, 8014, 7597, 7180, 6760,
+6340, 5919, 5496, 5073, 4649,
+4224, 3798, 3372, 2945, 2517,
+2090, 1661, 1233, 804, 375,
+-54, -483, -911, -1340, -1768,
+-2197, -2624, -3052, -3479, -3905,
+-4330, -4755, -5179, -5602, -6024,
+-6445, -6865, -7284, -7702, -8118,
+-8533, -8946, -9358, -9768, -10177,
+-10584, -10989, -11392, -11793, -12192,
+-12589, -12984, -13377, -13767, -14155,
+-14541, -14924, -15305, -15683, -16058,
+-16430, -16800, -17167, -17531, -17892,
+-18249, -18604, -18956, -19304, -19649,
+-19990, -20329, -20663, -20994, -21322,
+-21646, -21966, -22282, -22595, -22904,
+-23208, -23509, -23806, -24099, -24387,
+-24672, -24952, -25228, -25499, -25766,
+-26029, -26288, -26541, -26791, -27035,
+-27275, -27511, -27741, -27967, -28188,
+-28405, -28616, -28823, -29024, -29221,
+-29412, -29599, -29780, -29957, -30128,
+-30294, -30455, -30611, -30761, -30906,
+-31046, -31181, -31310, -31434, -31552,
+-31665, -31773, -31875, -31972, -32063,
+-32149, -32229, -32304, -32373, -32437,
+-32495, -32547, -32594, -32635, -32671,
+-32701, -32726, -32745, -32758, -32766,
+#endif
+};
+#endif
+
+static const CELTMode mode96000_1920_240 = {
+96000,    /* Fs */
+240,    /* overlap */
+21,    /* nbEBands */
+21,    /* effEBands */
+{30245, 7209, 6197, 5415, },    /* preemph */
+eband5ms,    /* eBands */
+3,    /* maxLM */
+8,    /* nbShortMdcts */
+240,    /* shortMdctSize */
+11,    /* nbAllocVectors */
+band_allocation,    /* allocVectors */
+logN400,    /* logN */
+window240,    /* window */
+{3840, 3, {&fft_state96000_1920_0, &fft_state96000_1920_1, &fft_state96000_1920_2, &fft_state96000_1920_3, }, mdct_twiddles1920},    /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50},    /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50},    /* qext_cache */
+#endif
+};
+#endif /* ENABLE_QEXT */
+
+/* List of all the available modes */
+#ifdef ENABLE_QEXT
+#define TOTAL_MODES 2
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+&mode96000_1920_240,
+};
+#else
+#define TOTAL_MODES 1
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+};
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed_arm_ne10.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_fixed_arm_ne10.h
new file mode 100644 (file)
index 0000000..7623092
--- /dev/null
@@ -0,0 +1,388 @@
+/* The contents of this file was automatically generated by
+ * dump_mode_arm_ne10.c with arguments: 48000 960
+ * It contains static definitions for some pre-defined modes. */
+#include <NE10_types.h>
+
+#ifndef NE10_FFT_PARAMS48000_960
+#define NE10_FFT_PARAMS48000_960
+static const ne10_int32_t ne10_factors_480[64] = {
+4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_240[64] = {
+3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_120[64] = {
+3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_60[64] = {
+2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_fft_cpx_int32_t ne10_twiddles_480[480] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955},
+{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330},
+{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738},
+{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141},
+{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240},
+{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960},
+{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282},
+{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339},
+{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564},
+{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839},
+{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918},
+{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188},
+{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252},
+{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059},
+{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542},
+{2147483647,0}, {2147299667,-28109693}, {2146747758,-56214570},
+{2145828015,-84309815}, {2144540595,-112390613}, {2142885719,-140452154},
+{2140863671,-168489630}, {2138474797,-196498235}, {2135719506,-224473172},
+{2132598271,-252409646}, {2129111626,-280302871}, {2125260168,-308148068},
+{2121044558,-335940465}, {2116465518,-363675300}, {2111523833,-391347822},
+{2106220349,-418953288}, {2100555974,-446486968}, {2094531681,-473944146},
+{2088148500,-501320115}, {2081407525,-528610186}, {2074309912,-555809682},
+{2066856885,-582913912}, {2059049696,-609918325}, {2050889698,-636818231},
+{2042378310,-663608960}, {2033516972,-690285983}, {2024307180,-716844791},
+{2014750533,-743280770}, {2004848691,-769589332}, {1994603329,-795766029},
+{1984016179,-821806435}, {1973089077,-847706028}, {1961823921,-873460313},
+{1950222618,-899064934}, {1938287127,-924515564}, {1926019520,-949807783},
+{1913421927,-974937199}, {1900496481,-999899565}, {1887245364,-1024690661},
+{1873670877,-1049306180}, {1859775377,-1073741851}, {1845561215,-1097993541},
+{1831030826,-1122057097}, {1816186632,-1145928502}, {1801031311,-1169603450},
+{1785567394,-1193077993}, {1769797456,-1216348214}, {1753724345,-1239409914},
+{1737350743,-1262259248}, {1720679456,-1284892300}, {1703713340,-1307305194},
+{1686455222,-1329494189}, {1668908218,-1351455280}, {1651075255,-1373184807},
+{1632959307,-1394679144}, {1614563642,-1415934412}, {1595891331,-1436947067},
+{1576945572,-1457713510}, {1557729613,-1478230181}, {1538246655,-1498493658},
+{1518500216,-1518500282}, {1498493590,-1538246721}, {1478230113,-1557729677},
+{1457713441,-1576945636}, {1436946998,-1595891394}, {1415934341,-1614563704},
+{1394679073,-1632959368}, {1373184735,-1651075315}, {1351455207,-1668908277},
+{1329494115,-1686455280}, {1307305120,-1703713397}, {1284892225,-1720679512},
+{1262259172,-1737350799}, {1239409837,-1753724400}, {1216348136,-1769797510},
+{1193077915,-1785567446}, {1169603371,-1801031362}, {1145928423,-1816186682},
+{1122057017,-1831030875}, {1097993571,-1845561197}, {1073741769,-1859775424},
+{1049305987,-1873670985}, {1024690635,-1887245378}, {999899482,-1900496524},
+{974937230,-1913421912}, {949807699,-1926019561}, {924515422,-1938287195},
+{899064965,-1950222603}, {873460227,-1961823959}, {847705824,-1973089164},
+{821806407,-1984016190}, {795765941,-1994603364}, {769589125,-2004848771},
+{743280682,-2014750566}, {716844642,-2024307233}, {690286016,-2033516961},
+{663608871,-2042378339}, {636818019,-2050889764}, {609918296,-2059049705},
+{582913822,-2066856911}, {555809715,-2074309903}, {528610126,-2081407540},
+{501319962,-2088148536}, {473944148,-2094531680}, {446486876,-2100555994},
+{418953102,-2106220386}, {391347792,-2111523838}, {363675176,-2116465540},
+{335940246,-2121044593}, {308148006,-2125260177}, {280302715,-2129111646},
+{252409648,-2132598271}, {224473078,-2135719516}, {196498046,-2138474814},
+{168489600,-2140863674}, {140452029,-2142885728}, {112390647,-2144540593},
+{84309753,-2145828017}, {56214412,-2146747762}, {28109695,-2147299667},
+{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613},
+{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871},
+{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968},
+{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325},
+{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332},
+{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564},
+{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851},
+{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214},
+{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280},
+{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181},
+{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394},
+{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397},
+{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362},
+{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378},
+{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959},
+{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233},
+{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903},
+{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838},
+{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516},
+{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762},
+{-94,-2147483647}, {-56214600,-2146747757}, {-112390835,-2144540584},
+{-168489787,-2140863659}, {-224473265,-2135719496}, {-280302901,-2129111622},
+{-335940431,-2121044564}, {-391347977,-2111523804}, {-446487060,-2100555955},
+{-501320144,-2088148493}, {-555809896,-2074309855}, {-609918476,-2059049651},
+{-663609049,-2042378281}, {-716844819,-2024307170}, {-769589300,-2004848703},
+{-821806581,-1984016118}, {-873460398,-1961823883}, {-924515591,-1938287114},
+{-974937397,-1913421827}, {-1024690575,-1887245411}, {-1073741932,-1859775330},
+{-1122057395,-1831030643}, {-1169603421,-1801031330}, {-1216348291,-1769797403},
+{-1262259116,-1737350839}, {-1307305268,-1703713283}, {-1351455453,-1668908078},
+{-1394679021,-1632959413}, {-1436947137,-1595891268}, {-1478230435,-1557729372},
+{-1518500258,-1518500240}, {-1557729742,-1478230045}, {-1595891628,-1436946738},
+{-1632959429,-1394679001}, {-1668908417,-1351455035}, {-1703713298,-1307305248},
+{-1737350854,-1262259096}, {-1769797708,-1216347848}, {-1801031344,-1169603400},
+{-1831030924,-1122056937}, {-1859775343,-1073741910}, {-1887245423,-1024690552},
+{-1913422071,-974936918}, {-1938287125,-924515568}, {-1961823997,-873460141},
+{-1984016324,-821806084}, {-2004848713,-769589276}, {-2024307264,-716844553},
+{-2042378447,-663608538}, {-2059049731,-609918206}, {-2074309994,-555809377},
+{-2088148499,-501320119}, {-2100556013,-446486785}, {-2111523902,-391347448},
+{-2121044568,-335940406}, {-2129111659,-280302621}, {-2135719499,-224473240},
+{-2140863681,-168489506}, {-2144540612,-112390298}, {-2146747758,-56214574},
+{2147483647,0}, {2145828015,-84309815}, {2140863671,-168489630},
+{2132598271,-252409646}, {2121044558,-335940465}, {2106220349,-418953288},
+{2088148500,-501320115}, {2066856885,-582913912}, {2042378310,-663608960},
+{2014750533,-743280770}, {1984016179,-821806435}, {1950222618,-899064934},
+{1913421927,-974937199}, {1873670877,-1049306180}, {1831030826,-1122057097},
+{1785567394,-1193077993}, {1737350743,-1262259248}, {1686455222,-1329494189},
+{1632959307,-1394679144}, {1576945572,-1457713510}, {1518500216,-1518500282},
+{1457713441,-1576945636}, {1394679073,-1632959368}, {1329494115,-1686455280},
+{1262259172,-1737350799}, {1193077915,-1785567446}, {1122057017,-1831030875},
+{1049305987,-1873670985}, {974937230,-1913421912}, {899064965,-1950222603},
+{821806407,-1984016190}, {743280682,-2014750566}, {663608871,-2042378339},
+{582913822,-2066856911}, {501319962,-2088148536}, {418953102,-2106220386},
+{335940246,-2121044593}, {252409648,-2132598271}, {168489600,-2140863674},
+{84309753,-2145828017}, {-94,-2147483647}, {-84309940,-2145828010},
+{-168489787,-2140863659}, {-252409834,-2132598249}, {-335940431,-2121044564},
+{-418953286,-2106220349}, {-501320144,-2088148493}, {-582914003,-2066856860},
+{-663609049,-2042378281}, {-743280858,-2014750501}, {-821806581,-1984016118},
+{-899065136,-1950222525}, {-974937397,-1913421827}, {-1049306374,-1873670768},
+{-1122057395,-1831030643}, {-1193078284,-1785567199}, {-1262259116,-1737350839},
+{-1329494061,-1686455323}, {-1394679021,-1632959413}, {-1457713485,-1576945595},
+{-1518500258,-1518500240}, {-1576945613,-1457713466}, {-1632959429,-1394679001},
+{-1686455338,-1329494041}, {-1737350854,-1262259096}, {-1785567498,-1193077837},
+{-1831030924,-1122056937}, {-1873671031,-1049305905}, {-1913422071,-974936918},
+{-1950222750,-899064648}, {-1984016324,-821806084}, {-2014750687,-743280354},
+{-2042378447,-663608538}, {-2066856867,-582913978}, {-2088148499,-501320119},
+{-2106220354,-418953261}, {-2121044568,-335940406}, {-2132598282,-252409555},
+{-2140863681,-168489506}, {-2145828021,-84309659}, {-2147483647,188},
+{-2145828006,84310034}, {-2140863651,168489881}, {-2132598237,252409928},
+{-2121044509,335940777}, {-2106220281,418953629}, {-2088148411,501320484},
+{-2066856765,582914339}, {-2042378331,663608895}, {-2014750557,743280706},
+{-1984016181,821806431}, {-1950222593,899064989}, {-1913421900,974937252},
+{-1873670848,1049306232}, {-1831030728,1122057257}, {-1785567289,1193078149},
+{-1737350633,1262259400}, {-1686455106,1329494336}, {-1632959185,1394679287},
+{-1576945358,1457713742}, {-1518499993,1518500506}, {-1457713209,1576945850},
+{-1394678735,1632959656}, {-1329493766,1686455555}, {-1262258813,1737351059},
+{-1193077546,1785567692}, {-1122056638,1831031107}, {-1049305599,1873671202},
+{-974936606,1913422229}, {-899064330,1950222896}, {-821805761,1984016458},
+{-743280025,2014750808}, {-663609179,2042378239}, {-582914134,2066856823},
+{-501320277,2088148461}, {-418953420,2106220322}, {-335940566,2121044542},
+{-252409716,2132598263}, {-168489668,2140863668}, {-84309821,2145828015},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_240[240] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248},
+{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647},
+{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096},
+{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895},
+{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239},
+{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613},
+{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871},
+{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968},
+{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325},
+{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332},
+{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564},
+{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851},
+{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214},
+{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280},
+{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181},
+{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394},
+{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397},
+{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362},
+{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378},
+{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959},
+{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233},
+{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903},
+{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838},
+{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516},
+{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{-94,-2147483647}, {-112390835,-2144540584}, {-224473265,-2135719496},
+{-335940431,-2121044564}, {-446487060,-2100555955}, {-555809896,-2074309855},
+{-663609049,-2042378281}, {-769589300,-2004848703}, {-873460398,-1961823883},
+{-974937397,-1913421827}, {-1073741932,-1859775330}, {-1169603421,-1801031330},
+{-1262259116,-1737350839}, {-1351455453,-1668908078}, {-1436947137,-1595891268},
+{-1518500258,-1518500240}, {-1595891628,-1436946738}, {-1668908417,-1351455035},
+{-1737350854,-1262259096}, {-1801031344,-1169603400}, {-1859775343,-1073741910},
+{-1913422071,-974936918}, {-1961823997,-873460141}, {-2004848713,-769589276},
+{-2042378447,-663608538}, {-2074309994,-555809377}, {-2100556013,-446486785},
+{-2121044568,-335940406}, {-2135719499,-224473240}, {-2144540612,-112390298},
+{2147483647,0}, {2140863671,-168489630}, {2121044558,-335940465},
+{2088148500,-501320115}, {2042378310,-663608960}, {1984016179,-821806435},
+{1913421927,-974937199}, {1831030826,-1122057097}, {1737350743,-1262259248},
+{1632959307,-1394679144}, {1518500216,-1518500282}, {1394679073,-1632959368},
+{1262259172,-1737350799}, {1122057017,-1831030875}, {974937230,-1913421912},
+{821806407,-1984016190}, {663608871,-2042378339}, {501319962,-2088148536},
+{335940246,-2121044593}, {168489600,-2140863674}, {-94,-2147483647},
+{-168489787,-2140863659}, {-335940431,-2121044564}, {-501320144,-2088148493},
+{-663609049,-2042378281}, {-821806581,-1984016118}, {-974937397,-1913421827},
+{-1122057395,-1831030643}, {-1262259116,-1737350839}, {-1394679021,-1632959413},
+{-1518500258,-1518500240}, {-1632959429,-1394679001}, {-1737350854,-1262259096},
+{-1831030924,-1122056937}, {-1913422071,-974936918}, {-1984016324,-821806084},
+{-2042378447,-663608538}, {-2088148499,-501320119}, {-2121044568,-335940406},
+{-2140863681,-168489506}, {-2147483647,188}, {-2140863651,168489881},
+{-2121044509,335940777}, {-2088148411,501320484}, {-2042378331,663608895},
+{-1984016181,821806431}, {-1913421900,974937252}, {-1831030728,1122057257},
+{-1737350633,1262259400}, {-1632959185,1394679287}, {-1518499993,1518500506},
+{-1394678735,1632959656}, {-1262258813,1737351059}, {-1122056638,1831031107},
+{-974936606,1913422229}, {-821805761,1984016458}, {-663609179,2042378239},
+{-501320277,2088148461}, {-335940566,2121044542}, {-168489668,2140863668},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_120[120] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955},
+{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330},
+{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738},
+{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141},
+{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240},
+{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960},
+{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282},
+{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339},
+{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564},
+{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839},
+{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918},
+{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188},
+{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252},
+{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059},
+{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_60[60] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248},
+{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647},
+{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096},
+{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895},
+{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239},
+};
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_480 = {
+120,
+(ne10_int32_t *)ne10_factors_480,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_480,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_480[120],
+};
+static const arch_fft_state cfg_arch_480 = {
+1,
+(void *)&ne10_fft_state_int32_t_480,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_240 = {
+60,
+(ne10_int32_t *)ne10_factors_240,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_240,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_240[60],
+};
+static const arch_fft_state cfg_arch_240 = {
+1,
+(void *)&ne10_fft_state_int32_t_240,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_120 = {
+30,
+(ne10_int32_t *)ne10_factors_120,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_120,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_120[30],
+};
+static const arch_fft_state cfg_arch_120 = {
+1,
+(void *)&ne10_fft_state_int32_t_120,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_60 = {
+15,
+(ne10_int32_t *)ne10_factors_60,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_60,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_60[15],
+};
+static const arch_fft_state cfg_arch_60 = {
+1,
+(void *)&ne10_fft_state_int32_t_60,
+};
+
+#endif  /* end NE10_FFT_PARAMS48000_960 */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float.h
new file mode 100644 (file)
index 0000000..1bccc3b
--- /dev/null
@@ -0,0 +1,2516 @@
+/* The contents of this file was automatically generated by dump_modes.c
+   with arguments: 48000 960 96000 1920
+   It contains static definitions for some pre-defined modes. */
+#include "modes.h"
+#include "rate.h"
+
+#ifdef HAVE_ARM_NE10
+#define OVERRIDE_FFT 1
+#include "static_modes_float_arm_ne10.h"
+#endif
+
+#ifndef DEF_WINDOW120
+#define DEF_WINDOW120
+static const celt_coef window120[120] = {
+6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f,
+0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f,
+0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f,
+0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f,
+0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f,
+0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f,
+0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f,
+0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f,
+0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f,
+0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f,
+0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f,
+0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f,
+0.71433873f, 0.72857055f, 0.74248043f, 0.75605425f, 0.76927895f,
+0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f,
+0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f,
+0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f,
+0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f,
+0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f,
+0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f,
+0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f,
+0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f,
+0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f,
+0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f,
+0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f,
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES48000_960
+#define FFT_TWIDDLES48000_960
+static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
+{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f},
+{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f},
+{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f},
+{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f},
+{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f},
+{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f},
+{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f},
+{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f},
+{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f},
+{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f},
+{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f},
+{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f},
+{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f},
+{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f},
+{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f},
+{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f},
+{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f},
+{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f},
+{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f},
+{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f},
+{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f},
+{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f},
+{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f},
+{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f},
+{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f},
+{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f},
+{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f},
+{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f},
+{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f},
+{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f},
+{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f},
+{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f},
+{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f},
+{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f},
+{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f},
+{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f},
+{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f},
+{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f},
+{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f},
+{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f},
+{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f},
+{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f},
+{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f},
+{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f},
+{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f},
+{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f},
+{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f},
+{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f},
+{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f},
+{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f},
+{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f},
+{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f},
+{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f},
+{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f},
+{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f},
+{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f},
+{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f},
+{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f},
+{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f},
+{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f},
+{6.1232340e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f},
+{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f},
+{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f},
+{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f},
+{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f},
+{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f},
+{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f},
+{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f},
+{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f},
+{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f},
+{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f},
+{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f},
+{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f},
+{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f},
+{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f},
+{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f},
+{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f},
+{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f},
+{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f},
+{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f},
+{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f},
+{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f},
+{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f},
+{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f},
+{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f},
+{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f},
+{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f},
+{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f},
+{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f},
+{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f},
+{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f},
+{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f},
+{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f},
+{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f},
+{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f},
+{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f},
+{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f},
+{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f},
+{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f},
+{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f},
+{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f},
+{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f},
+{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f},
+{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f},
+{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f},
+{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f},
+{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f},
+{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f},
+{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f},
+{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f},
+{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f},
+{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f},
+{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f},
+{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f},
+{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f},
+{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f},
+{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f},
+{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f},
+{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f},
+{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f},
+{-1.0000000f, -1.2246468e-16f}, {-0.99991433f, 0.013089596f},
+{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f},
+{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f},
+{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f},
+{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f},
+{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f},
+{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f},
+{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f},
+{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f},
+{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f},
+{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f},
+{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f},
+{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f},
+{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f},
+{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f},
+{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f},
+{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f},
+{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f},
+{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f},
+{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f},
+{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f},
+{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f},
+{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f},
+{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f},
+{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f},
+{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f},
+{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f},
+{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f},
+{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f},
+{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f},
+{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f},
+{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f},
+{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f},
+{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f},
+{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f},
+{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f},
+{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f},
+{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f},
+{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f},
+{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f},
+{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f},
+{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f},
+{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f},
+{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f},
+{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f},
+{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f},
+{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f},
+{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f},
+{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f},
+{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f},
+{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f},
+{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f},
+{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f},
+{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f},
+{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f},
+{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f},
+{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f},
+{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f},
+{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f},
+{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f},
+{-1.8369702e-16f, 1.0000000f}, {0.013089596f, 0.99991433f},
+{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f},
+{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f},
+{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f},
+{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f},
+{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f},
+{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f},
+{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f},
+{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f},
+{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f},
+{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f},
+{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f},
+{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f},
+{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f},
+{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f},
+{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f},
+{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f},
+{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f},
+{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f},
+{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f},
+{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f},
+{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f},
+{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f},
+{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f},
+{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f},
+{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f},
+{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f},
+{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f},
+{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f},
+{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f},
+{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f},
+{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f},
+{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f},
+{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f},
+{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f},
+{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f},
+{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f},
+{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f},
+{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f},
+{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f},
+{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f},
+{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f},
+{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f},
+{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f},
+{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f},
+{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f},
+{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f},
+{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f},
+{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f},
+{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f},
+{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f},
+{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f},
+{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f},
+{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f},
+{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f},
+{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f},
+{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f},
+{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f},
+{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f},
+{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f},
+};
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_BITREV60
+#define FFT_BITREV60
+static const opus_int16 fft_bitrev60[60] = {
+0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
+1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
+2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
+3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
+};
+#endif
+
+#ifndef FFT_STATE48000_960_0
+#define FFT_STATE48000_960_0
+static const kiss_fft_state fft_state48000_960_0 = {
+480,    /* nfft */
+0.0020833334f,    /* scale */
+-1,    /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev480,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_1
+#define FFT_STATE48000_960_1
+static const kiss_fft_state fft_state48000_960_1 = {
+240,    /* nfft */
+0.0041666669f,    /* scale */
+1,    /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev240,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_2
+#define FFT_STATE48000_960_2
+static const kiss_fft_state fft_state48000_960_2 = {
+120,    /* nfft */
+0.0083333338f,    /* scale */
+2,    /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev120,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_3
+#define FFT_STATE48000_960_3
+static const kiss_fft_state fft_state48000_960_3 = {
+60,    /* nfft */
+0.016666668f,    /* scale */
+3,    /* shift */
+{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev60,    /* bitrev */
+fft_twiddles48000_960,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_60,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES960
+#define MDCT_TWIDDLES960
+static const celt_coef mdct_twiddles960[1800] = {
+0.99999992f, 0.99999322f, 0.99997582f, 0.99994771f, 0.99990889f,
+0.99985936f, 0.99979913f, 0.99972818f, 0.99964653f, 0.99955418f,
+0.99945112f, 0.99933736f, 0.99921289f, 0.99907773f, 0.99893186f,
+0.99877530f, 0.99860804f, 0.99843009f, 0.99824144f, 0.99804211f,
+0.99783209f, 0.99761138f, 0.99737998f, 0.99713791f, 0.99688516f,
+0.99662173f, 0.99634763f, 0.99606285f, 0.99576741f, 0.99546131f,
+0.99514455f, 0.99481713f, 0.99447905f, 0.99413033f, 0.99377096f,
+0.99340095f, 0.99302029f, 0.99262901f, 0.99222709f, 0.99181455f,
+0.99139139f, 0.99095760f, 0.99051321f, 0.99005821f, 0.98959261f,
+0.98911641f, 0.98862961f, 0.98813223f, 0.98762427f, 0.98710573f,
+0.98657662f, 0.98603694f, 0.98548670f, 0.98492591f, 0.98435457f,
+0.98377269f, 0.98318028f, 0.98257734f, 0.98196387f, 0.98133989f,
+0.98070539f, 0.98006040f, 0.97940491f, 0.97873893f, 0.97806247f,
+0.97737554f, 0.97667813f, 0.97597027f, 0.97525196f, 0.97452320f,
+0.97378401f, 0.97303439f, 0.97227435f, 0.97150389f, 0.97072303f,
+0.96993178f, 0.96913014f, 0.96831812f, 0.96749573f, 0.96666298f,
+0.96581987f, 0.96496643f, 0.96410265f, 0.96322854f, 0.96234412f,
+0.96144939f, 0.96054437f, 0.95962906f, 0.95870347f, 0.95776762f,
+0.95682151f, 0.95586515f, 0.95489856f, 0.95392174f, 0.95293471f,
+0.95193746f, 0.95093003f, 0.94991241f, 0.94888462f, 0.94784667f,
+0.94679856f, 0.94574032f, 0.94467195f, 0.94359346f, 0.94250486f,
+0.94140618f, 0.94029741f, 0.93917857f, 0.93804967f, 0.93691073f,
+0.93576176f, 0.93460276f, 0.93343375f, 0.93225475f, 0.93106577f,
+0.92986681f, 0.92865789f, 0.92743903f, 0.92621024f, 0.92497153f,
+0.92372291f, 0.92246440f, 0.92119602f, 0.91991776f, 0.91862966f,
+0.91733172f, 0.91602395f, 0.91470637f, 0.91337900f, 0.91204185f,
+0.91069493f, 0.90933825f, 0.90797184f, 0.90659570f, 0.90520986f,
+0.90381432f, 0.90240910f, 0.90099422f, 0.89956969f, 0.89813553f,
+0.89669174f, 0.89523836f, 0.89377538f, 0.89230284f, 0.89082074f,
+0.88932910f, 0.88782793f, 0.88631726f, 0.88479710f, 0.88326746f,
+0.88172836f, 0.88017982f, 0.87862185f, 0.87705448f, 0.87547771f,
+0.87389156f, 0.87229606f, 0.87069121f, 0.86907704f, 0.86745357f,
+0.86582080f, 0.86417876f, 0.86252747f, 0.86086694f, 0.85919719f,
+0.85751824f, 0.85583010f, 0.85413281f, 0.85242636f, 0.85071078f,
+0.84898610f, 0.84725232f, 0.84550947f, 0.84375756f, 0.84199662f,
+0.84022666f, 0.83844771f, 0.83665977f, 0.83486287f, 0.83305704f,
+0.83124228f, 0.82941862f, 0.82758608f, 0.82574467f, 0.82389442f,
+0.82203535f, 0.82016748f, 0.81829082f, 0.81640540f, 0.81451123f,
+0.81260835f, 0.81069676f, 0.80877649f, 0.80684755f, 0.80490998f,
+0.80296379f, 0.80100899f, 0.79904562f, 0.79707370f, 0.79509323f,
+0.79310425f, 0.79110678f, 0.78910084f, 0.78708644f, 0.78506362f,
+0.78303239f, 0.78099277f, 0.77894479f, 0.77688847f, 0.77482382f,
+0.77275088f, 0.77066967f, 0.76858020f, 0.76648250f, 0.76437659f,
+0.76226250f, 0.76014024f, 0.75800984f, 0.75587132f, 0.75372471f,
+0.75157003f, 0.74940730f, 0.74723654f, 0.74505779f, 0.74287105f,
+0.74067635f, 0.73847373f, 0.73626320f, 0.73404478f, 0.73181850f,
+0.72958438f, 0.72734245f, 0.72509273f, 0.72283525f, 0.72057002f,
+0.71829708f, 0.71601644f, 0.71372814f, 0.71143220f, 0.70912863f,
+0.70681747f, 0.70449874f, 0.70217247f, 0.69983868f, 0.69749739f,
+0.69514863f, 0.69279243f, 0.69042881f, 0.68805780f, 0.68567941f,
+0.68329369f, 0.68090064f, 0.67850031f, 0.67609270f, 0.67367786f,
+0.67125580f, 0.66882656f, 0.66639015f, 0.66394661f, 0.66149595f,
+0.65903821f, 0.65657341f, 0.65410159f, 0.65162275f, 0.64913694f,
+0.64664418f, 0.64414449f, 0.64163790f, 0.63912444f, 0.63660414f,
+0.63407702f, 0.63154311f, 0.62900244f, 0.62645503f, 0.62390091f,
+0.62134011f, 0.61877265f, 0.61619857f, 0.61361789f, 0.61103064f,
+0.60843685f, 0.60583654f, 0.60322974f, 0.60061648f, 0.59799679f,
+0.59537069f, 0.59273822f, 0.59009940f, 0.58745427f, 0.58480284f,
+0.58214514f, 0.57948122f, 0.57681109f, 0.57413478f, 0.57145232f,
+0.56876374f, 0.56606907f, 0.56336834f, 0.56066158f, 0.55794881f,
+0.55523006f, 0.55250537f, 0.54977477f, 0.54703827f, 0.54429592f,
+0.54154774f, 0.53879376f, 0.53603401f, 0.53326852f, 0.53049731f,
+0.52772043f, 0.52493790f, 0.52214974f, 0.51935599f, 0.51655668f,
+0.51375184f, 0.51094149f, 0.50812568f, 0.50530442f, 0.50247775f,
+0.49964570f, 0.49680830f, 0.49396558f, 0.49111757f, 0.48826430f,
+0.48540580f, 0.48254210f, 0.47967323f, 0.47679923f, 0.47392012f,
+0.47103594f, 0.46814671f, 0.46525247f, 0.46235324f, 0.45944907f,
+0.45653997f, 0.45362599f, 0.45070714f, 0.44778347f, 0.44485501f,
+0.44192178f, 0.43898381f, 0.43604115f, 0.43309382f, 0.43014185f,
+0.42718527f, 0.42422412f, 0.42125842f, 0.41828822f, 0.41531353f,
+0.41233440f, 0.40935085f, 0.40636291f, 0.40337063f, 0.40037402f,
+0.39737313f, 0.39436798f, 0.39135861f, 0.38834505f, 0.38532733f,
+0.38230548f, 0.37927953f, 0.37624953f, 0.37321550f, 0.37017747f,
+0.36713547f, 0.36408955f, 0.36103972f, 0.35798603f, 0.35492850f,
+0.35186718f, 0.34880208f, 0.34573325f, 0.34266072f, 0.33958451f,
+0.33650468f, 0.33342123f, 0.33033422f, 0.32724367f, 0.32414961f,
+0.32105209f, 0.31795112f, 0.31484675f, 0.31173901f, 0.30862793f,
+0.30551354f, 0.30239588f, 0.29927499f, 0.29615089f, 0.29302362f,
+0.28989321f, 0.28675969f, 0.28362310f, 0.28048348f, 0.27734085f,
+0.27419526f, 0.27104672f, 0.26789529f, 0.26474098f, 0.26158384f,
+0.25842390f, 0.25526119f, 0.25209575f, 0.24892761f, 0.24575680f,
+0.24258336f, 0.23940732f, 0.23622872f, 0.23304759f, 0.22986396f,
+0.22667787f, 0.22348935f, 0.22029844f, 0.21710517f, 0.21390958f,
+0.21071169f, 0.20751155f, 0.20430919f, 0.20110463f, 0.19789793f,
+0.19468910f, 0.19147819f, 0.18826523f, 0.18505026f, 0.18183330f,
+0.17861439f, 0.17539357f, 0.17217088f, 0.16894634f, 0.16571999f,
+0.16249186f, 0.15926200f, 0.15603043f, 0.15279719f, 0.14956231f,
+0.14632583f, 0.14308778f, 0.13984820f, 0.13660713f, 0.13336459f,
+0.13012062f, 0.12687526f, 0.12362854f, 0.12038049f, 0.11713116f,
+0.11388057f, 0.11062877f, 0.10737578f, 0.10412163f, 0.10086638f,
+0.097610040f, 0.094352658f, 0.091094266f, 0.087834897f, 0.084574589f,
+0.081313374f, 0.078051289f, 0.074788367f, 0.071524645f, 0.068260157f,
+0.064994938f, 0.061729023f, 0.058462447f, 0.055195244f, 0.051927451f,
+0.048659101f, 0.045390231f, 0.042120874f, 0.038851066f, 0.035580842f,
+0.032310238f, 0.029039287f, 0.025768025f, 0.022496487f, 0.019224708f,
+0.015952723f, 0.012680568f, 0.0094082767f, 0.0061358846f, 0.0028634269f,
+-0.00040906153f, -0.0036815456f, -0.0069539902f, -0.010226360f, -0.013498621f,
+-0.016770737f, -0.020042673f, -0.023314395f, -0.026585867f, -0.029857055f,
+-0.033127923f, -0.036398436f, -0.039668559f, -0.042938257f, -0.046207495f,
+-0.049476239f, -0.052744453f, -0.056012102f, -0.059279151f, -0.062545565f,
+-0.065811309f, -0.069076349f, -0.072340649f, -0.075604174f, -0.078866890f,
+-0.082128761f, -0.085389752f, -0.088649829f, -0.091908956f, -0.095167100f,
+-0.098424224f, -0.10168029f, -0.10493528f, -0.10818913f, -0.11144183f,
+-0.11469334f, -0.11794361f, -0.12119263f, -0.12444034f, -0.12768673f,
+-0.13093174f, -0.13417536f, -0.13741753f, -0.14065824f, -0.14389744f,
+-0.14713510f, -0.15037118f, -0.15360565f, -0.15683848f, -0.16006962f,
+-0.16329906f, -0.16652674f, -0.16975264f, -0.17297673f, -0.17619896f,
+-0.17941930f, -0.18263772f, -0.18585419f, -0.18906866f, -0.19228112f,
+-0.19549151f, -0.19869981f, -0.20190598f, -0.20510998f, -0.20831180f,
+-0.21151138f, -0.21470869f, -0.21790371f, -0.22109639f, -0.22428671f,
+-0.22747462f, -0.23066010f, -0.23384310f, -0.23702361f, -0.24020157f,
+-0.24337696f, -0.24654975f, -0.24971989f, -0.25288736f, -0.25605213f,
+-0.25921415f, -0.26237339f, -0.26552983f, -0.26868342f, -0.27183413f,
+-0.27498193f, -0.27812679f, -0.28126867f, -0.28440754f, -0.28754336f,
+-0.29067610f, -0.29380573f, -0.29693221f, -0.30005551f, -0.30317560f,
+-0.30629245f, -0.30940601f, -0.31251626f, -0.31562316f, -0.31872668f,
+-0.32182679f, -0.32492345f, -0.32801664f, -0.33110631f, -0.33419243f,
+-0.33727497f, -0.34035391f, -0.34342920f, -0.34650081f, -0.34956871f,
+-0.35263286f, -0.35569324f, -0.35874981f, -0.36180254f, -0.36485139f,
+-0.36789634f, -0.37093735f, -0.37397438f, -0.37700741f, -0.38003640f,
+-0.38306132f, -0.38608214f, -0.38909883f, -0.39211135f, -0.39511967f,
+-0.39812375f, -0.40112358f, -0.40411910f, -0.40711031f, -0.41009715f,
+-0.41307959f, -0.41605762f, -0.41903119f, -0.42200027f, -0.42496483f,
+-0.42792484f, -0.43088027f, -0.43383109f, -0.43677726f, -0.43971875f,
+-0.44265553f, -0.44558757f, -0.44851484f, -0.45143731f, -0.45435494f,
+-0.45726770f, -0.46017557f, -0.46307851f, -0.46597650f, -0.46886949f,
+-0.47175746f, -0.47464038f, -0.47751821f, -0.48039093f, -0.48325851f,
+-0.48612091f, -0.48897811f, -0.49183006f, -0.49467676f, -0.49751815f,
+-0.50035422f, -0.50318492f, -0.50601024f, -0.50883014f, -0.51164459f,
+-0.51445356f, -0.51725703f, -0.52005495f, -0.52284730f, -0.52563406f,
+-0.52841518f, -0.53119065f, -0.53396043f, -0.53672449f, -0.53948280f,
+-0.54223533f, -0.54498206f, -0.54772295f, -0.55045797f, -0.55318710f,
+-0.55591031f, -0.55862756f, -0.56133883f, -0.56404409f, -0.56674331f,
+-0.56943646f, -0.57212351f, -0.57480443f, -0.57747920f, -0.58014778f,
+-0.58281015f, -0.58546628f, -0.58811614f, -0.59075970f, -0.59339694f,
+-0.59602782f, -0.59865231f, -0.60127040f, -0.60388204f, -0.60648722f,
+-0.60908591f, -0.61167807f, -0.61426368f, -0.61684271f, -0.61941514f,
+-0.62198093f, -0.62454007f, -0.62709251f, -0.62963824f, -0.63217722f,
+-0.63470944f, -0.63723486f, -0.63975345f, -0.64226519f, -0.64477006f,
+-0.64726802f, -0.64975905f, -0.65224312f, -0.65472020f, -0.65719027f,
+-0.65965331f, -0.66210928f, -0.66455816f, -0.66699992f, -0.66943454f,
+-0.67186199f, -0.67428225f, -0.67669528f, -0.67910107f, -0.68149959f,
+-0.68389080f, -0.68627470f, -0.68865124f, -0.69102041f, -0.69338218f,
+-0.69573652f, -0.69808341f, -0.70042283f, -0.70275474f, -0.70507913f,
+-0.70739597f, -0.70970524f, -0.71200690f, -0.71430093f, -0.71658732f,
+-0.71886604f, -0.72113705f, -0.72340034f, -0.72565589f, -0.72790366f,
+-0.73014364f, -0.73237580f, -0.73460012f, -0.73681657f, -0.73902513f,
+-0.74122577f, -0.74341848f, -0.74560322f, -0.74777998f, -0.74994874f,
+-0.75210946f, -0.75426212f, -0.75640671f, -0.75854320f, -0.76067157f,
+-0.76279178f, -0.76490383f, -0.76700769f, -0.76910334f, -0.77119075f,
+-0.77326989f, -0.77534076f, -0.77740333f, -0.77945757f, -0.78150346f,
+-0.78354098f, -0.78557011f, -0.78759083f, -0.78960312f, -0.79160694f,
+-0.79360229f, -0.79558915f, -0.79756748f, -0.79953727f, -0.80149850f,
+-0.80345114f, -0.80539518f, -0.80733060f, -0.80925737f, -0.81117547f,
+-0.81308489f, -0.81498559f, -0.81687757f, -0.81876081f, -0.82063527f,
+-0.82250095f, -0.82435781f, -0.82620585f, -0.82804505f, -0.82987537f,
+-0.83169681f, -0.83350933f, -0.83531294f, -0.83710760f, -0.83889329f,
+-0.84067000f, -0.84243770f, -0.84419639f, -0.84594603f, -0.84768662f,
+-0.84941812f, -0.85114053f, -0.85285383f, -0.85455799f, -0.85625300f,
+-0.85793884f, -0.85961549f, -0.86128294f, -0.86294116f, -0.86459014f,
+-0.86622986f, -0.86786031f, -0.86948146f, -0.87109330f, -0.87269581f,
+-0.87428898f, -0.87587278f, -0.87744720f, -0.87901223f, -0.88056784f,
+-0.88211402f, -0.88365076f, -0.88517803f, -0.88669582f, -0.88820412f,
+-0.88970290f, -0.89119216f, -0.89267187f, -0.89414203f, -0.89560260f,
+-0.89705359f, -0.89849497f, -0.89992673f, -0.90134885f, -0.90276131f,
+-0.90416411f, -0.90555723f, -0.90694065f, -0.90831436f, -0.90967833f,
+-0.91103257f, -0.91237705f, -0.91371176f, -0.91503669f, -0.91635181f,
+-0.91765712f, -0.91895261f, -0.92023825f, -0.92151404f, -0.92277996f,
+-0.92403600f, -0.92528214f, -0.92651837f, -0.92774468f, -0.92896106f,
+-0.93016748f, -0.93136395f, -0.93255044f, -0.93372694f, -0.93489345f,
+-0.93604994f, -0.93719641f, -0.93833284f, -0.93945922f, -0.94057555f,
+-0.94168180f, -0.94277796f, -0.94386403f, -0.94493999f, -0.94600583f,
+-0.94706154f, -0.94810711f, -0.94914252f, -0.95016777f, -0.95118284f,
+-0.95218773f, -0.95318242f, -0.95416690f, -0.95514117f, -0.95610520f,
+-0.95705900f, -0.95800255f, -0.95893583f, -0.95985885f, -0.96077159f,
+-0.96167404f, -0.96256619f, -0.96344803f, -0.96431956f, -0.96518076f,
+-0.96603162f, -0.96687213f, -0.96770230f, -0.96852209f, -0.96933152f,
+-0.97013057f, -0.97091922f, -0.97169748f, -0.97246533f, -0.97322277f,
+-0.97396979f, -0.97470637f, -0.97543252f, -0.97614822f, -0.97685347f,
+-0.97754825f, -0.97823257f, -0.97890641f, -0.97956977f, -0.98022263f,
+-0.98086500f, -0.98149687f, -0.98211822f, -0.98272906f, -0.98332937f,
+-0.98391915f, -0.98449840f, -0.98506710f, -0.98562525f, -0.98617285f,
+-0.98670988f, -0.98723635f, -0.98775225f, -0.98825757f, -0.98875230f,
+-0.98923645f, -0.98971000f, -0.99017295f, -0.99062530f, -0.99106704f,
+-0.99149817f, -0.99191868f, -0.99232857f, -0.99272783f, -0.99311645f,
+-0.99349445f, -0.99386180f, -0.99421851f, -0.99456457f, -0.99489998f,
+-0.99522474f, -0.99553884f, -0.99584227f, -0.99613505f, -0.99641715f,
+-0.99668858f, -0.99694934f, -0.99719943f, -0.99743883f, -0.99766756f,
+-0.99788559f, -0.99809295f, -0.99828961f, -0.99847558f, -0.99865086f,
+-0.99881544f, -0.99896933f, -0.99911252f, -0.99924501f, -0.99936680f,
+-0.99947789f, -0.99957827f, -0.99966795f, -0.99974692f, -0.99981519f,
+-0.99987275f, -0.99991960f, -0.99995574f, -0.99998118f, -0.99999590f,
+0.99999967f, 0.99997289f, 0.99990328f, 0.99979084f, 0.99963557f,
+0.99943748f, 0.99919658f, 0.99891288f, 0.99858638f, 0.99821711f,
+0.99780508f, 0.99735031f, 0.99685281f, 0.99631261f, 0.99572973f,
+0.99510420f, 0.99443605f, 0.99372529f, 0.99297196f, 0.99217610f,
+0.99133774f, 0.99045692f, 0.98953366f, 0.98856802f, 0.98756003f,
+0.98650973f, 0.98541718f, 0.98428242f, 0.98310549f, 0.98188645f,
+0.98062534f, 0.97932224f, 0.97797718f, 0.97659022f, 0.97516144f,
+0.97369088f, 0.97217861f, 0.97062469f, 0.96902920f, 0.96739220f,
+0.96571376f, 0.96399395f, 0.96223284f, 0.96043052f, 0.95858705f,
+0.95670253f, 0.95477702f, 0.95281061f, 0.95080338f, 0.94875543f,
+0.94666684f, 0.94453769f, 0.94236808f, 0.94015810f, 0.93790786f,
+0.93561743f, 0.93328693f, 0.93091644f, 0.92850608f, 0.92605595f,
+0.92356614f, 0.92103677f, 0.91846795f, 0.91585979f, 0.91321239f,
+0.91052587f, 0.90780035f, 0.90503595f, 0.90223277f, 0.89939095f,
+0.89651059f, 0.89359184f, 0.89063481f, 0.88763962f, 0.88460641f,
+0.88153531f, 0.87842644f, 0.87527995f, 0.87209596f, 0.86887462f,
+0.86561605f, 0.86232041f, 0.85898782f, 0.85561844f, 0.85221241f,
+0.84876987f, 0.84529098f, 0.84177587f, 0.83822471f, 0.83463763f,
+0.83101481f, 0.82735639f, 0.82366252f, 0.81993338f, 0.81616911f,
+0.81236987f, 0.80853584f, 0.80466718f, 0.80076404f, 0.79682660f,
+0.79285503f, 0.78884950f, 0.78481017f, 0.78073723f, 0.77663084f,
+0.77249118f, 0.76831844f, 0.76411277f, 0.75987438f, 0.75560344f,
+0.75130013f, 0.74696464f, 0.74259715f, 0.73819784f, 0.73376692f,
+0.72930457f, 0.72481097f, 0.72028632f, 0.71573083f, 0.71114467f,
+0.70652804f, 0.70188116f, 0.69720420f, 0.69249738f, 0.68776090f,
+0.68299495f, 0.67819975f, 0.67337550f, 0.66852240f, 0.66364066f,
+0.65873050f, 0.65379211f, 0.64882573f, 0.64383154f, 0.63880978f,
+0.63376065f, 0.62868438f, 0.62358117f, 0.61845126f, 0.61329485f,
+0.60811216f, 0.60290343f, 0.59766888f, 0.59240872f, 0.58712318f,
+0.58181249f, 0.57647688f, 0.57111658f, 0.56573181f, 0.56032281f,
+0.55488980f, 0.54943303f, 0.54395272f, 0.53844911f, 0.53292243f,
+0.52737292f, 0.52180083f, 0.51620638f, 0.51058981f, 0.50495138f,
+0.49929132f, 0.49360987f, 0.48790727f, 0.48218377f, 0.47643962f,
+0.47067506f, 0.46489034f, 0.45908570f, 0.45326139f, 0.44741768f,
+0.44155479f, 0.43567299f, 0.42977253f, 0.42385365f, 0.41791662f,
+0.41196169f, 0.40598911f, 0.39999914f, 0.39399204f, 0.38796806f,
+0.38192746f, 0.37587050f, 0.36979743f, 0.36370853f, 0.35760405f,
+0.35148424f, 0.34534939f, 0.33919973f, 0.33303555f, 0.32685710f,
+0.32066465f, 0.31445847f, 0.30823881f, 0.30200595f, 0.29576015f,
+0.28950169f, 0.28323082f, 0.27694782f, 0.27065295f, 0.26434649f,
+0.25802871f, 0.25169988f, 0.24536026f, 0.23901013f, 0.23264977f,
+0.22627944f, 0.21989941f, 0.21350997f, 0.20711138f, 0.20070391f,
+0.19428785f, 0.18786347f, 0.18143104f, 0.17499084f, 0.16854314f,
+0.16208822f, 0.15562636f, 0.14915783f, 0.14268292f, 0.13620189f,
+0.12971502f, 0.12322260f, 0.11672491f, 0.11022221f, 0.10371479f,
+0.097202924f, 0.090686897f, 0.084166986f, 0.077643468f, 0.071116625f,
+0.064586736f, 0.058054080f, 0.051518937f, 0.044981587f, 0.038442310f,
+0.031901387f, 0.025359097f, 0.018815721f, 0.012271538f, 0.0057268303f,
+-0.00081812300f, -0.0073630412f, -0.013907644f, -0.020451651f, -0.026994782f,
+-0.033536757f, -0.040077295f, -0.046616116f, -0.053152941f, -0.059687488f,
+-0.066219479f, -0.072748633f, -0.079274670f, -0.085797312f, -0.092316279f,
+-0.098831291f, -0.10534207f, -0.11184834f, -0.11834981f, -0.12484622f,
+-0.13133727f, -0.13782270f, -0.14430223f, -0.15077558f, -0.15724246f,
+-0.16370261f, -0.17015575f, -0.17660160f, -0.18303989f, -0.18947033f,
+-0.19589266f, -0.20230660f, -0.20871187f, -0.21510820f, -0.22149531f,
+-0.22787294f, -0.23424080f, -0.24059864f, -0.24694616f, -0.25328311f,
+-0.25960920f, -0.26592418f, -0.27222777f, -0.27851969f, -0.28479968f,
+-0.29106748f, -0.29732280f, -0.30356539f, -0.30979497f, -0.31601129f,
+-0.32221406f, -0.32840304f, -0.33457794f, -0.34073852f, -0.34688450f,
+-0.35301562f, -0.35913161f, -0.36523223f, -0.37131719f, -0.37738626f,
+-0.38343915f, -0.38947562f, -0.39549541f, -0.40149825f, -0.40748390f,
+-0.41345209f, -0.41940257f, -0.42533508f, -0.43124938f, -0.43714520f,
+-0.44302229f, -0.44888041f, -0.45471930f, -0.46053871f, -0.46633839f,
+-0.47211810f, -0.47787758f, -0.48361659f, -0.48933489f, -0.49503222f,
+-0.50070835f, -0.50636303f, -0.51199602f, -0.51760707f, -0.52319595f,
+-0.52876243f, -0.53430625f, -0.53982718f, -0.54532499f, -0.55079944f,
+-0.55625029f, -0.56167732f, -0.56708028f, -0.57245896f, -0.57781311f,
+-0.58314251f, -0.58844693f, -0.59372614f, -0.59897992f, -0.60420805f,
+-0.60941029f, -0.61458642f, -0.61973623f, -0.62485949f, -0.62995598f,
+-0.63502549f, -0.64006780f, -0.64508268f, -0.65006994f, -0.65502934f,
+-0.65996069f, -0.66486377f, -0.66973837f, -0.67458427f, -0.67940128f,
+-0.68418919f, -0.68894779f, -0.69367688f, -0.69837625f, -0.70304571f,
+-0.70768504f, -0.71229407f, -0.71687258f, -0.72142039f, -0.72593729f,
+-0.73042309f, -0.73487761f, -0.73930064f, -0.74369201f, -0.74805152f,
+-0.75237898f, -0.75667422f, -0.76093704f, -0.76516727f, -0.76936471f,
+-0.77352921f, -0.77766056f, -0.78175861f, -0.78582316f, -0.78985406f,
+-0.79385112f, -0.79781417f, -0.80174305f, -0.80563758f, -0.80949760f,
+-0.81332295f, -0.81711346f, -0.82086896f, -0.82458930f, -0.82827432f,
+-0.83192386f, -0.83553776f, -0.83911587f, -0.84265803f, -0.84616410f,
+-0.84963392f, -0.85306735f, -0.85646423f, -0.85982442f, -0.86314779f,
+-0.86643418f, -0.86968345f, -0.87289547f, -0.87607009f, -0.87920719f,
+-0.88230663f, -0.88536827f, -0.88839199f, -0.89137765f, -0.89432512f,
+-0.89723429f, -0.90010502f, -0.90293719f, -0.90573069f, -0.90848539f,
+-0.91120117f, -0.91387791f, -0.91651551f, -0.91911385f, -0.92167282f,
+-0.92419231f, -0.92667220f, -0.92911240f, -0.93151280f, -0.93387330f,
+-0.93619380f, -0.93847419f, -0.94071438f, -0.94291427f, -0.94507377f,
+-0.94719279f, -0.94927123f, -0.95130901f, -0.95330604f, -0.95526223f,
+-0.95717750f, -0.95905177f, -0.96088496f, -0.96267699f, -0.96442777f,
+-0.96613725f, -0.96780534f, -0.96943197f, -0.97101707f, -0.97256058f,
+-0.97406243f, -0.97552255f, -0.97694089f, -0.97831737f, -0.97965195f,
+-0.98094456f, -0.98219515f, -0.98340367f, -0.98457006f, -0.98569428f,
+-0.98677627f, -0.98781599f, -0.98881340f, -0.98976845f, -0.99068110f,
+-0.99155132f, -0.99237906f, -0.99316428f, -0.99390697f, -0.99460708f,
+-0.99526458f, -0.99587945f, -0.99645166f, -0.99698119f, -0.99746801f,
+-0.99791210f, -0.99831344f, -0.99867202f, -0.99898782f, -0.99926082f,
+-0.99949102f, -0.99967841f, -0.99982297f, -0.99992470f, -0.99998360f,
+0.99999866f, 0.99989157f, 0.99961315f, 0.99916346f, 0.99854256f,
+0.99775057f, 0.99678762f, 0.99565388f, 0.99434953f, 0.99287481f,
+0.99122996f, 0.98941527f, 0.98743105f, 0.98527764f, 0.98295541f,
+0.98046475f, 0.97780610f, 0.97497990f, 0.97198664f, 0.96882685f,
+0.96550104f, 0.96200980f, 0.95835373f, 0.95453345f, 0.95054962f,
+0.94640291f, 0.94209404f, 0.93762375f, 0.93299280f, 0.92820199f,
+0.92325213f, 0.91814408f, 0.91287871f, 0.90745693f, 0.90187965f,
+0.89614785f, 0.89026249f, 0.88422459f, 0.87803519f, 0.87169533f,
+0.86520612f, 0.85856866f, 0.85178409f, 0.84485357f, 0.83777828f,
+0.83055945f, 0.82319831f, 0.81569611f, 0.80805415f, 0.80027373f,
+0.79235620f, 0.78430289f, 0.77611520f, 0.76779452f, 0.75934229f,
+0.75075995f, 0.74204897f, 0.73321084f, 0.72424708f, 0.71515923f,
+0.70594883f, 0.69661748f, 0.68716676f, 0.67759830f, 0.66791374f,
+0.65811474f, 0.64820297f, 0.63818013f, 0.62804795f, 0.61780815f,
+0.60746249f, 0.59701275f, 0.58646072f, 0.57580819f, 0.56505701f,
+0.55420900f, 0.54326604f, 0.53222998f, 0.52110274f, 0.50988620f,
+0.49858230f, 0.48719297f, 0.47572016f, 0.46416584f, 0.45253199f,
+0.44082059f, 0.42903367f, 0.41717323f, 0.40524131f, 0.39323996f,
+0.38117123f, 0.36903718f, 0.35683990f, 0.34458148f, 0.33226402f,
+0.31988962f, 0.30746042f, 0.29497853f, 0.28244610f, 0.26986527f,
+0.25723821f, 0.24456706f, 0.23185402f, 0.21910124f, 0.20631092f,
+0.19348526f, 0.18062644f, 0.16773667f, 0.15481816f, 0.14187312f,
+0.12890377f, 0.11591234f, 0.10290104f, 0.089872115f, 0.076827789f,
+0.063770300f, 0.050701883f, 0.037624779f, 0.024541229f, 0.011453473f,
+-0.0016362454f, -0.014725683f, -0.027812598f, -0.040894747f, -0.053969889f,
+-0.067035784f, -0.080090192f, -0.093130877f, -0.10615561f, -0.11916214f,
+-0.13214826f, -0.14511174f, -0.15805036f, -0.17096189f, -0.18384413f,
+-0.19669487f, -0.20951190f, -0.22229304f, -0.23503609f, -0.24773886f,
+-0.26039919f, -0.27301490f, -0.28558383f, -0.29810383f, -0.31057274f,
+-0.32298845f, -0.33534881f, -0.34765171f, -0.35989504f, -0.37207670f,
+-0.38419461f, -0.39624670f, -0.40823088f, -0.42014512f, -0.43198737f,
+-0.44375560f, -0.45544780f, -0.46706195f, -0.47859608f, -0.49004821f,
+-0.50141636f, -0.51269860f, -0.52389299f, -0.53499762f, -0.54601058f,
+-0.55692998f, -0.56775395f, -0.57848064f, -0.58910822f, -0.59963485f,
+-0.61005873f, -0.62037809f, -0.63059115f, -0.64069616f, -0.65069139f,
+-0.66057513f, -0.67034568f, -0.68000137f, -0.68954054f, -0.69896157f,
+-0.70826283f, -0.71744274f, -0.72649972f, -0.73543221f, -0.74423869f,
+-0.75291765f, -0.76146760f, -0.76988708f, -0.77817464f, -0.78632887f,
+-0.79434836f, -0.80223175f, -0.80997767f, -0.81758481f, -0.82505187f,
+-0.83237755f, -0.83956061f, -0.84659981f, -0.85349396f, -0.86024186f,
+-0.86684237f, -0.87329434f, -0.87959669f, -0.88574831f, -0.89174817f,
+-0.89759523f, -0.90328850f, -0.90882699f, -0.91420976f, -0.91943588f,
+-0.92450446f, -0.92941463f, -0.93416555f, -0.93875641f, -0.94318642f,
+-0.94745482f, -0.95156087f, -0.95550388f, -0.95928317f, -0.96289809f,
+-0.96634802f, -0.96963238f, -0.97275059f, -0.97570213f, -0.97848649f,
+-0.98110318f, -0.98355177f, -0.98583184f, -0.98794298f, -0.98988485f,
+-0.99165711f, -0.99325945f, -0.99469160f, -0.99595331f, -0.99704438f,
+-0.99796460f, -0.99871383f, -0.99929194f, -0.99969882f, -0.99993441f,
+0.99999465f, 0.99956631f, 0.99845292f, 0.99665524f, 0.99417450f,
+0.99101241f, 0.98717112f, 0.98265328f, 0.97746197f, 0.97160077f,
+0.96507367f, 0.95788516f, 0.95004017f, 0.94154407f, 0.93240267f,
+0.92262226f, 0.91220953f, 0.90117161f, 0.88951608f, 0.87725091f,
+0.86438452f, 0.85092573f, 0.83688375f, 0.82226822f, 0.80708914f,
+0.79135693f, 0.77508236f, 0.75827658f, 0.74095113f, 0.72311786f,
+0.70478900f, 0.68597711f, 0.66669509f, 0.64695615f, 0.62677382f,
+0.60616193f, 0.58513461f, 0.56370626f, 0.54189158f, 0.51970551f,
+0.49716327f, 0.47428029f, 0.45107226f, 0.42755509f, 0.40374490f,
+0.37965800f, 0.35531090f, 0.33072029f, 0.30590302f, 0.28087610f,
+0.25565668f, 0.23026205f, 0.20470960f, 0.17901686f, 0.15320143f,
+0.12728100f, 0.10127334f, 0.075196277f, 0.049067674f, 0.022905443f,
+-0.0032724865f, -0.029448173f, -0.055603678f, -0.081721074f, -0.10778246f,
+-0.13376998f, -0.15966582f, -0.18545224f, -0.21111155f, -0.23662618f,
+-0.26197864f, -0.28715155f, -0.31212766f, -0.33688985f, -0.36142116f,
+-0.38570477f, -0.40972403f, -0.43346249f, -0.45690388f, -0.48003212f,
+-0.50283138f, -0.52528602f, -0.54738066f, -0.56910015f, -0.59042960f,
+-0.61135441f, -0.63186022f, -0.65193299f, -0.67155895f, -0.69072467f,
+-0.70941699f, -0.72762312f, -0.74533057f, -0.76252720f, -0.77920124f,
+-0.79534126f, -0.81093618f, -0.82597533f, -0.84044840f, -0.85434547f,
+-0.86765701f, -0.88037390f, -0.89248743f, -0.90398929f, -0.91487161f,
+-0.92512691f, -0.93474818f, -0.94372882f, -0.95206268f, -0.95974404f,
+-0.96676764f, -0.97312866f, -0.97882275f, -0.98384601f, -0.98819498f,
+-0.99186670f, -0.99485864f, -0.99716875f, -0.99879546f, -0.99973764f,
+};
+#endif
+
+static const CELTMode mode48000_960_120 = {
+48000,    /* Fs */
+120,    /* overlap */
+21,    /* nbEBands */
+21,    /* effEBands */
+{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, },    /* preemph */
+eband5ms,    /* eBands */
+3,    /* maxLM */
+8,    /* nbShortMdcts */
+120,    /* shortMdctSize */
+11,    /* nbAllocVectors */
+band_allocation,    /* allocVectors */
+logN400,    /* logN */
+window120,    /* window */
+{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960},    /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50},    /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50},    /* qext_cache */
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#ifndef DEF_WINDOW240
+#define DEF_WINDOW240
+static const celt_coef window240[240] = {
+1.6821922e-05f, 0.00015139297f, 0.00042051200f, 0.00082413284f, 0.0013621862f,
+0.0020345793f, 0.0028411964f, 0.0037818978f, 0.0048565203f, 0.0060648765f,
+0.0074067550f, 0.0088819198f, 0.010490110f, 0.012231040f, 0.014104398f,
+0.016109846f, 0.018247021f, 0.020515533f, 0.022914963f, 0.025444867f,
+0.028104770f, 0.030894170f, 0.033812535f, 0.036859304f, 0.040033885f,
+0.043335654f, 0.046763958f, 0.050318110f, 0.053997389f, 0.057801044f,
+0.061728287f, 0.065778297f, 0.069950217f, 0.074243155f, 0.078656182f,
+0.083188331f, 0.087838600f, 0.092605946f, 0.097489289f, 0.10248751f,
+0.10759945f, 0.11282390f, 0.11815964f, 0.12360536f, 0.12915977f,
+0.13482147f, 0.14058908f, 0.14646113f, 0.15243614f, 0.15851256f,
+0.16468882f, 0.17096330f, 0.17733432f, 0.18380017f, 0.19035910f,
+0.19700930f, 0.20374894f, 0.21057612f, 0.21748892f, 0.22448537f,
+0.23156343f, 0.23872106f, 0.24595615f, 0.25326656f, 0.26065010f,
+0.26810455f, 0.27562763f, 0.28321704f, 0.29087045f, 0.29858546f,
+0.30635965f, 0.31419058f, 0.32207574f, 0.33001263f, 0.33799866f,
+0.34603127f, 0.35410783f, 0.36222570f, 0.37038219f, 0.37857460f,
+0.38680022f, 0.39505629f, 0.40334003f, 0.41164867f, 0.41997939f,
+0.42832937f, 0.43669576f, 0.44507572f, 0.45346639f, 0.46186489f,
+0.47026835f, 0.47867389f, 0.48707862f, 0.49547965f, 0.50387411f,
+0.51225912f, 0.52063179f, 0.52898927f, 0.53732871f, 0.54564725f,
+0.55394208f, 0.56221039f, 0.57044938f, 0.57865628f, 0.58682836f,
+0.59496289f, 0.60305718f, 0.61110858f, 0.61911445f, 0.62707221f,
+0.63497931f, 0.64283322f, 0.65063147f, 0.65837163f, 0.66605132f,
+0.67366820f, 0.68121999f, 0.68870444f, 0.69611937f, 0.70346266f,
+0.71073222f, 0.71792606f, 0.72504220f, 0.73207877f, 0.73903393f,
+0.74590592f, 0.75269303f, 0.75939364f, 0.76600617f, 0.77252915f,
+0.77896113f, 0.78530077f, 0.79154678f, 0.79769796f, 0.80375317f,
+0.80971135f, 0.81557152f, 0.82133276f, 0.82699424f, 0.83255520f,
+0.83801496f, 0.84337291f, 0.84862851f, 0.85378132f, 0.85883095f,
+0.86377710f, 0.86861954f, 0.87335813f, 0.87799277f, 0.88252347f,
+0.88695029f, 0.89127338f, 0.89549294f, 0.89960926f, 0.90362268f,
+0.90753364f, 0.91134262f, 0.91505017f, 0.91865692f, 0.92216354f,
+0.92557078f, 0.92887945f, 0.93209042f, 0.93520460f, 0.93822298f,
+0.94114659f, 0.94397652f, 0.94671390f, 0.94935993f, 0.95191584f,
+0.95438290f, 0.95676245f, 0.95905584f, 0.96126449f, 0.96338982f,
+0.96543334f, 0.96739653f, 0.96928096f, 0.97108818f, 0.97281981f,
+0.97447746f, 0.97606279f, 0.97757746f, 0.97902317f, 0.98040162f,
+0.98171453f, 0.98296363f, 0.98415067f, 0.98527740f, 0.98634557f,
+0.98735696f, 0.98831332f, 0.98921643f, 0.99006803f, 0.99086991f,
+0.99162380f, 0.99233145f, 0.99299461f, 0.99361500f, 0.99419433f,
+0.99473429f, 0.99523657f, 0.99570284f, 0.99613472f, 0.99653384f,
+0.99690180f, 0.99724017f, 0.99755048f, 0.99783426f, 0.99809299f,
+0.99832812f, 0.99854108f, 0.99873324f, 0.99890597f, 0.99906057f,
+0.99919832f, 0.99932046f, 0.99942819f, 0.99952266f, 0.99960498f,
+0.99967623f, 0.99973742f, 0.99978953f, 0.99983351f, 0.99987023f,
+0.99990053f, 0.99992520f, 0.99994498f, 0.99996055f, 0.99997257f,
+0.99998161f, 0.99998821f, 0.99999285f, 0.99999596f, 0.99999793f,
+0.99999907f, 0.99999966f, 0.99999991f, 0.99999999f, 1.0000000f,
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES96000_1920
+#define FFT_TWIDDLES96000_1920
+static const kiss_twiddle_cpx fft_twiddles96000_1920[960] = {
+{1.0000000f, -0.0000000f}, {0.99997858f, -0.0065449380f},
+{0.99991433f, -0.013089596f}, {0.99980724f, -0.019633692f},
+{0.99965732f, -0.026176948f}, {0.99946459f, -0.032719083f},
+{0.99922904f, -0.039259816f}, {0.99895068f, -0.045798867f},
+{0.99862953f, -0.052335956f}, {0.99826561f, -0.058870804f},
+{0.99785892f, -0.065403129f}, {0.99740949f, -0.071932653f},
+{0.99691733f, -0.078459096f}, {0.99638247f, -0.084982177f},
+{0.99580493f, -0.091501619f}, {0.99518473f, -0.098017140f},
+{0.99452190f, -0.10452846f}, {0.99381646f, -0.11103531f},
+{0.99306846f, -0.11753740f}, {0.99227791f, -0.12403445f},
+{0.99144486f, -0.13052619f}, {0.99056934f, -0.13701234f},
+{0.98965139f, -0.14349262f}, {0.98869104f, -0.14996676f},
+{0.98768834f, -0.15643447f}, {0.98664333f, -0.16289547f},
+{0.98555606f, -0.16934950f}, {0.98442657f, -0.17579628f},
+{0.98325491f, -0.18223553f}, {0.98204113f, -0.18866696f},
+{0.98078528f, -0.19509032f}, {0.97948742f, -0.20150532f},
+{0.97814760f, -0.20791169f}, {0.97676588f, -0.21430915f},
+{0.97534232f, -0.22069744f}, {0.97387698f, -0.22707626f},
+{0.97236992f, -0.23344536f}, {0.97082121f, -0.23980446f},
+{0.96923091f, -0.24615329f}, {0.96759909f, -0.25249158f},
+{0.96592583f, -0.25881905f}, {0.96421118f, -0.26513543f},
+{0.96245524f, -0.27144045f}, {0.96065806f, -0.27773385f},
+{0.95881973f, -0.28401534f}, {0.95694034f, -0.29028468f},
+{0.95501994f, -0.29654157f}, {0.95305864f, -0.30278577f},
+{0.95105652f, -0.30901699f}, {0.94901365f, -0.31523498f},
+{0.94693013f, -0.32143947f}, {0.94480605f, -0.32763018f},
+{0.94264149f, -0.33380686f}, {0.94043656f, -0.33996924f},
+{0.93819134f, -0.34611706f}, {0.93590593f, -0.35225005f},
+{0.93358043f, -0.35836795f}, {0.93121493f, -0.36447050f},
+{0.92880955f, -0.37055744f}, {0.92636438f, -0.37662850f},
+{0.92387953f, -0.38268343f}, {0.92135511f, -0.38872197f},
+{0.91879121f, -0.39474386f}, {0.91618796f, -0.40074883f},
+{0.91354546f, -0.40673664f}, {0.91086382f, -0.41270703f},
+{0.90814317f, -0.41865974f}, {0.90538362f, -0.42459451f},
+{0.90258528f, -0.43051110f}, {0.89974828f, -0.43640924f},
+{0.89687274f, -0.44228869f}, {0.89395878f, -0.44814919f},
+{0.89100652f, -0.45399050f}, {0.88801610f, -0.45981236f},
+{0.88498764f, -0.46561452f}, {0.88192126f, -0.47139674f},
+{0.87881711f, -0.47715876f}, {0.87567532f, -0.48290034f},
+{0.87249601f, -0.48862124f}, {0.86927932f, -0.49432121f},
+{0.86602540f, -0.50000000f}, {0.86273439f, -0.50565737f},
+{0.85940641f, -0.51129309f}, {0.85604162f, -0.51690690f},
+{0.85264016f, -0.52249856f}, {0.84920218f, -0.52806785f},
+{0.84572782f, -0.53361452f}, {0.84221723f, -0.53913832f},
+{0.83867057f, -0.54463904f}, {0.83508798f, -0.55011642f},
+{0.83146961f, -0.55557023f}, {0.82781563f, -0.56100025f},
+{0.82412619f, -0.56640624f}, {0.82040144f, -0.57178796f},
+{0.81664156f, -0.57714519f}, {0.81284668f, -0.58247770f},
+{0.80901699f, -0.58778525f}, {0.80515265f, -0.59306763f},
+{0.80125381f, -0.59832460f}, {0.79732065f, -0.60355594f},
+{0.79335334f, -0.60876143f}, {0.78935204f, -0.61394084f},
+{0.78531693f, -0.61909395f}, {0.78124818f, -0.62422054f},
+{0.77714596f, -0.62932039f}, {0.77301045f, -0.63439328f},
+{0.76884183f, -0.63943900f}, {0.76464028f, -0.64445733f},
+{0.76040597f, -0.64944805f}, {0.75613908f, -0.65441095f},
+{0.75183981f, -0.65934582f}, {0.74750833f, -0.66425244f},
+{0.74314483f, -0.66913061f}, {0.73874949f, -0.67398011f},
+{0.73432251f, -0.67880075f}, {0.72986407f, -0.68359230f},
+{0.72537437f, -0.68835458f}, {0.72085360f, -0.69308736f},
+{0.71630194f, -0.69779046f}, {0.71171961f, -0.70246367f},
+{0.70710678f, -0.70710678f}, {0.70246367f, -0.71171961f},
+{0.69779046f, -0.71630194f}, {0.69308736f, -0.72085360f},
+{0.68835458f, -0.72537437f}, {0.68359230f, -0.72986407f},
+{0.67880075f, -0.73432251f}, {0.67398011f, -0.73874949f},
+{0.66913061f, -0.74314483f}, {0.66425244f, -0.74750833f},
+{0.65934582f, -0.75183981f}, {0.65441095f, -0.75613908f},
+{0.64944805f, -0.76040597f}, {0.64445733f, -0.76464028f},
+{0.63943900f, -0.76884183f}, {0.63439328f, -0.77301045f},
+{0.62932039f, -0.77714596f}, {0.62422054f, -0.78124818f},
+{0.61909395f, -0.78531693f}, {0.61394084f, -0.78935204f},
+{0.60876143f, -0.79335334f}, {0.60355594f, -0.79732065f},
+{0.59832460f, -0.80125381f}, {0.59306763f, -0.80515265f},
+{0.58778525f, -0.80901699f}, {0.58247770f, -0.81284668f},
+{0.57714519f, -0.81664156f}, {0.57178796f, -0.82040144f},
+{0.56640624f, -0.82412619f}, {0.56100025f, -0.82781563f},
+{0.55557023f, -0.83146961f}, {0.55011642f, -0.83508798f},
+{0.54463904f, -0.83867057f}, {0.53913832f, -0.84221723f},
+{0.53361452f, -0.84572782f}, {0.52806785f, -0.84920218f},
+{0.52249856f, -0.85264016f}, {0.51690690f, -0.85604162f},
+{0.51129309f, -0.85940641f}, {0.50565737f, -0.86273439f},
+{0.50000000f, -0.86602540f}, {0.49432121f, -0.86927932f},
+{0.48862124f, -0.87249601f}, {0.48290034f, -0.87567532f},
+{0.47715876f, -0.87881711f}, {0.47139674f, -0.88192126f},
+{0.46561452f, -0.88498764f}, {0.45981236f, -0.88801610f},
+{0.45399050f, -0.89100652f}, {0.44814919f, -0.89395878f},
+{0.44228869f, -0.89687274f}, {0.43640924f, -0.89974828f},
+{0.43051110f, -0.90258528f}, {0.42459451f, -0.90538362f},
+{0.41865974f, -0.90814317f}, {0.41270703f, -0.91086382f},
+{0.40673664f, -0.91354546f}, {0.40074883f, -0.91618796f},
+{0.39474386f, -0.91879121f}, {0.38872197f, -0.92135511f},
+{0.38268343f, -0.92387953f}, {0.37662850f, -0.92636438f},
+{0.37055744f, -0.92880955f}, {0.36447050f, -0.93121493f},
+{0.35836795f, -0.93358043f}, {0.35225005f, -0.93590593f},
+{0.34611706f, -0.93819134f}, {0.33996924f, -0.94043656f},
+{0.33380686f, -0.94264149f}, {0.32763018f, -0.94480605f},
+{0.32143947f, -0.94693013f}, {0.31523498f, -0.94901365f},
+{0.30901699f, -0.95105652f}, {0.30278577f, -0.95305864f},
+{0.29654157f, -0.95501994f}, {0.29028468f, -0.95694034f},
+{0.28401534f, -0.95881973f}, {0.27773385f, -0.96065806f},
+{0.27144045f, -0.96245524f}, {0.26513543f, -0.96421118f},
+{0.25881905f, -0.96592583f}, {0.25249158f, -0.96759909f},
+{0.24615329f, -0.96923091f}, {0.23980446f, -0.97082121f},
+{0.23344536f, -0.97236992f}, {0.22707626f, -0.97387698f},
+{0.22069744f, -0.97534232f}, {0.21430915f, -0.97676588f},
+{0.20791169f, -0.97814760f}, {0.20150532f, -0.97948742f},
+{0.19509032f, -0.98078528f}, {0.18866696f, -0.98204113f},
+{0.18223553f, -0.98325491f}, {0.17579628f, -0.98442657f},
+{0.16934950f, -0.98555606f}, {0.16289547f, -0.98664333f},
+{0.15643447f, -0.98768834f}, {0.14996676f, -0.98869104f},
+{0.14349262f, -0.98965139f}, {0.13701234f, -0.99056934f},
+{0.13052619f, -0.99144486f}, {0.12403445f, -0.99227791f},
+{0.11753740f, -0.99306846f}, {0.11103531f, -0.99381646f},
+{0.10452846f, -0.99452190f}, {0.098017140f, -0.99518473f},
+{0.091501619f, -0.99580493f}, {0.084982177f, -0.99638247f},
+{0.078459096f, -0.99691733f}, {0.071932653f, -0.99740949f},
+{0.065403129f, -0.99785892f}, {0.058870804f, -0.99826561f},
+{0.052335956f, -0.99862953f}, {0.045798867f, -0.99895068f},
+{0.039259816f, -0.99922904f}, {0.032719083f, -0.99946459f},
+{0.026176948f, -0.99965732f}, {0.019633692f, -0.99980724f},
+{0.013089596f, -0.99991433f}, {0.0065449380f, -0.99997858f},
+{6.1232340e-17f, -1.0000000f}, {-0.0065449380f, -0.99997858f},
+{-0.013089596f, -0.99991433f}, {-0.019633692f, -0.99980724f},
+{-0.026176948f, -0.99965732f}, {-0.032719083f, -0.99946459f},
+{-0.039259816f, -0.99922904f}, {-0.045798867f, -0.99895068f},
+{-0.052335956f, -0.99862953f}, {-0.058870804f, -0.99826561f},
+{-0.065403129f, -0.99785892f}, {-0.071932653f, -0.99740949f},
+{-0.078459096f, -0.99691733f}, {-0.084982177f, -0.99638247f},
+{-0.091501619f, -0.99580493f}, {-0.098017140f, -0.99518473f},
+{-0.10452846f, -0.99452190f}, {-0.11103531f, -0.99381646f},
+{-0.11753740f, -0.99306846f}, {-0.12403445f, -0.99227791f},
+{-0.13052619f, -0.99144486f}, {-0.13701234f, -0.99056934f},
+{-0.14349262f, -0.98965139f}, {-0.14996676f, -0.98869104f},
+{-0.15643447f, -0.98768834f}, {-0.16289547f, -0.98664333f},
+{-0.16934950f, -0.98555606f}, {-0.17579628f, -0.98442657f},
+{-0.18223553f, -0.98325491f}, {-0.18866696f, -0.98204113f},
+{-0.19509032f, -0.98078528f}, {-0.20150532f, -0.97948742f},
+{-0.20791169f, -0.97814760f}, {-0.21430915f, -0.97676588f},
+{-0.22069744f, -0.97534232f}, {-0.22707626f, -0.97387698f},
+{-0.23344536f, -0.97236992f}, {-0.23980446f, -0.97082121f},
+{-0.24615329f, -0.96923091f}, {-0.25249158f, -0.96759909f},
+{-0.25881905f, -0.96592583f}, {-0.26513543f, -0.96421118f},
+{-0.27144045f, -0.96245524f}, {-0.27773385f, -0.96065806f},
+{-0.28401534f, -0.95881973f}, {-0.29028468f, -0.95694034f},
+{-0.29654157f, -0.95501994f}, {-0.30278577f, -0.95305864f},
+{-0.30901699f, -0.95105652f}, {-0.31523498f, -0.94901365f},
+{-0.32143947f, -0.94693013f}, {-0.32763018f, -0.94480605f},
+{-0.33380686f, -0.94264149f}, {-0.33996924f, -0.94043656f},
+{-0.34611706f, -0.93819134f}, {-0.35225005f, -0.93590593f},
+{-0.35836795f, -0.93358043f}, {-0.36447050f, -0.93121493f},
+{-0.37055744f, -0.92880955f}, {-0.37662850f, -0.92636438f},
+{-0.38268343f, -0.92387953f}, {-0.38872197f, -0.92135511f},
+{-0.39474386f, -0.91879121f}, {-0.40074883f, -0.91618796f},
+{-0.40673664f, -0.91354546f}, {-0.41270703f, -0.91086382f},
+{-0.41865974f, -0.90814317f}, {-0.42459451f, -0.90538362f},
+{-0.43051110f, -0.90258528f}, {-0.43640924f, -0.89974828f},
+{-0.44228869f, -0.89687274f}, {-0.44814919f, -0.89395878f},
+{-0.45399050f, -0.89100652f}, {-0.45981236f, -0.88801610f},
+{-0.46561452f, -0.88498764f}, {-0.47139674f, -0.88192126f},
+{-0.47715876f, -0.87881711f}, {-0.48290034f, -0.87567532f},
+{-0.48862124f, -0.87249601f}, {-0.49432121f, -0.86927932f},
+{-0.50000000f, -0.86602540f}, {-0.50565737f, -0.86273439f},
+{-0.51129309f, -0.85940641f}, {-0.51690690f, -0.85604162f},
+{-0.52249856f, -0.85264016f}, {-0.52806785f, -0.84920218f},
+{-0.53361452f, -0.84572782f}, {-0.53913832f, -0.84221723f},
+{-0.54463904f, -0.83867057f}, {-0.55011642f, -0.83508798f},
+{-0.55557023f, -0.83146961f}, {-0.56100025f, -0.82781563f},
+{-0.56640624f, -0.82412619f}, {-0.57178796f, -0.82040144f},
+{-0.57714519f, -0.81664156f}, {-0.58247770f, -0.81284668f},
+{-0.58778525f, -0.80901699f}, {-0.59306763f, -0.80515265f},
+{-0.59832460f, -0.80125381f}, {-0.60355594f, -0.79732065f},
+{-0.60876143f, -0.79335334f}, {-0.61394084f, -0.78935204f},
+{-0.61909395f, -0.78531693f}, {-0.62422054f, -0.78124818f},
+{-0.62932039f, -0.77714596f}, {-0.63439328f, -0.77301045f},
+{-0.63943900f, -0.76884183f}, {-0.64445733f, -0.76464028f},
+{-0.64944805f, -0.76040597f}, {-0.65441095f, -0.75613908f},
+{-0.65934582f, -0.75183981f}, {-0.66425244f, -0.74750833f},
+{-0.66913061f, -0.74314483f}, {-0.67398011f, -0.73874949f},
+{-0.67880075f, -0.73432251f}, {-0.68359230f, -0.72986407f},
+{-0.68835458f, -0.72537437f}, {-0.69308736f, -0.72085360f},
+{-0.69779046f, -0.71630194f}, {-0.70246367f, -0.71171961f},
+{-0.70710678f, -0.70710678f}, {-0.71171961f, -0.70246367f},
+{-0.71630194f, -0.69779046f}, {-0.72085360f, -0.69308736f},
+{-0.72537437f, -0.68835458f}, {-0.72986407f, -0.68359230f},
+{-0.73432251f, -0.67880075f}, {-0.73874949f, -0.67398011f},
+{-0.74314483f, -0.66913061f}, {-0.74750833f, -0.66425244f},
+{-0.75183981f, -0.65934582f}, {-0.75613908f, -0.65441095f},
+{-0.76040597f, -0.64944805f}, {-0.76464028f, -0.64445733f},
+{-0.76884183f, -0.63943900f}, {-0.77301045f, -0.63439328f},
+{-0.77714596f, -0.62932039f}, {-0.78124818f, -0.62422054f},
+{-0.78531693f, -0.61909395f}, {-0.78935204f, -0.61394084f},
+{-0.79335334f, -0.60876143f}, {-0.79732065f, -0.60355594f},
+{-0.80125381f, -0.59832460f}, {-0.80515265f, -0.59306763f},
+{-0.80901699f, -0.58778525f}, {-0.81284668f, -0.58247770f},
+{-0.81664156f, -0.57714519f}, {-0.82040144f, -0.57178796f},
+{-0.82412619f, -0.56640624f}, {-0.82781563f, -0.56100025f},
+{-0.83146961f, -0.55557023f}, {-0.83508798f, -0.55011642f},
+{-0.83867057f, -0.54463904f}, {-0.84221723f, -0.53913832f},
+{-0.84572782f, -0.53361452f}, {-0.84920218f, -0.52806785f},
+{-0.85264016f, -0.52249856f}, {-0.85604162f, -0.51690690f},
+{-0.85940641f, -0.51129309f}, {-0.86273439f, -0.50565737f},
+{-0.86602540f, -0.50000000f}, {-0.86927932f, -0.49432121f},
+{-0.87249601f, -0.48862124f}, {-0.87567532f, -0.48290034f},
+{-0.87881711f, -0.47715876f}, {-0.88192126f, -0.47139674f},
+{-0.88498764f, -0.46561452f}, {-0.88801610f, -0.45981236f},
+{-0.89100652f, -0.45399050f}, {-0.89395878f, -0.44814919f},
+{-0.89687274f, -0.44228869f}, {-0.89974828f, -0.43640924f},
+{-0.90258528f, -0.43051110f}, {-0.90538362f, -0.42459451f},
+{-0.90814317f, -0.41865974f}, {-0.91086382f, -0.41270703f},
+{-0.91354546f, -0.40673664f}, {-0.91618796f, -0.40074883f},
+{-0.91879121f, -0.39474386f}, {-0.92135511f, -0.38872197f},
+{-0.92387953f, -0.38268343f}, {-0.92636438f, -0.37662850f},
+{-0.92880955f, -0.37055744f}, {-0.93121493f, -0.36447050f},
+{-0.93358043f, -0.35836795f}, {-0.93590593f, -0.35225005f},
+{-0.93819134f, -0.34611706f}, {-0.94043656f, -0.33996924f},
+{-0.94264149f, -0.33380686f}, {-0.94480605f, -0.32763018f},
+{-0.94693013f, -0.32143947f}, {-0.94901365f, -0.31523498f},
+{-0.95105652f, -0.30901699f}, {-0.95305864f, -0.30278577f},
+{-0.95501994f, -0.29654157f}, {-0.95694034f, -0.29028468f},
+{-0.95881973f, -0.28401534f}, {-0.96065806f, -0.27773385f},
+{-0.96245524f, -0.27144045f}, {-0.96421118f, -0.26513543f},
+{-0.96592583f, -0.25881905f}, {-0.96759909f, -0.25249158f},
+{-0.96923091f, -0.24615329f}, {-0.97082121f, -0.23980446f},
+{-0.97236992f, -0.23344536f}, {-0.97387698f, -0.22707626f},
+{-0.97534232f, -0.22069744f}, {-0.97676588f, -0.21430915f},
+{-0.97814760f, -0.20791169f}, {-0.97948742f, -0.20150532f},
+{-0.98078528f, -0.19509032f}, {-0.98204113f, -0.18866696f},
+{-0.98325491f, -0.18223553f}, {-0.98442657f, -0.17579628f},
+{-0.98555606f, -0.16934950f}, {-0.98664333f, -0.16289547f},
+{-0.98768834f, -0.15643447f}, {-0.98869104f, -0.14996676f},
+{-0.98965139f, -0.14349262f}, {-0.99056934f, -0.13701234f},
+{-0.99144486f, -0.13052619f}, {-0.99227791f, -0.12403445f},
+{-0.99306846f, -0.11753740f}, {-0.99381646f, -0.11103531f},
+{-0.99452190f, -0.10452846f}, {-0.99518473f, -0.098017140f},
+{-0.99580493f, -0.091501619f}, {-0.99638247f, -0.084982177f},
+{-0.99691733f, -0.078459096f}, {-0.99740949f, -0.071932653f},
+{-0.99785892f, -0.065403129f}, {-0.99826561f, -0.058870804f},
+{-0.99862953f, -0.052335956f}, {-0.99895068f, -0.045798867f},
+{-0.99922904f, -0.039259816f}, {-0.99946459f, -0.032719083f},
+{-0.99965732f, -0.026176948f}, {-0.99980724f, -0.019633692f},
+{-0.99991433f, -0.013089596f}, {-0.99997858f, -0.0065449380f},
+{-1.0000000f, -1.2246468e-16f}, {-0.99997858f, 0.0065449380f},
+{-0.99991433f, 0.013089596f}, {-0.99980724f, 0.019633692f},
+{-0.99965732f, 0.026176948f}, {-0.99946459f, 0.032719083f},
+{-0.99922904f, 0.039259816f}, {-0.99895068f, 0.045798867f},
+{-0.99862953f, 0.052335956f}, {-0.99826561f, 0.058870804f},
+{-0.99785892f, 0.065403129f}, {-0.99740949f, 0.071932653f},
+{-0.99691733f, 0.078459096f}, {-0.99638247f, 0.084982177f},
+{-0.99580493f, 0.091501619f}, {-0.99518473f, 0.098017140f},
+{-0.99452190f, 0.10452846f}, {-0.99381646f, 0.11103531f},
+{-0.99306846f, 0.11753740f}, {-0.99227791f, 0.12403445f},
+{-0.99144486f, 0.13052619f}, {-0.99056934f, 0.13701234f},
+{-0.98965139f, 0.14349262f}, {-0.98869104f, 0.14996676f},
+{-0.98768834f, 0.15643447f}, {-0.98664333f, 0.16289547f},
+{-0.98555606f, 0.16934950f}, {-0.98442657f, 0.17579628f},
+{-0.98325491f, 0.18223553f}, {-0.98204113f, 0.18866696f},
+{-0.98078528f, 0.19509032f}, {-0.97948742f, 0.20150532f},
+{-0.97814760f, 0.20791169f}, {-0.97676588f, 0.21430915f},
+{-0.97534232f, 0.22069744f}, {-0.97387698f, 0.22707626f},
+{-0.97236992f, 0.23344536f}, {-0.97082121f, 0.23980446f},
+{-0.96923091f, 0.24615329f}, {-0.96759909f, 0.25249158f},
+{-0.96592583f, 0.25881905f}, {-0.96421118f, 0.26513543f},
+{-0.96245524f, 0.27144045f}, {-0.96065806f, 0.27773385f},
+{-0.95881973f, 0.28401534f}, {-0.95694034f, 0.29028468f},
+{-0.95501994f, 0.29654157f}, {-0.95305864f, 0.30278577f},
+{-0.95105652f, 0.30901699f}, {-0.94901365f, 0.31523498f},
+{-0.94693013f, 0.32143947f}, {-0.94480605f, 0.32763018f},
+{-0.94264149f, 0.33380686f}, {-0.94043656f, 0.33996924f},
+{-0.93819134f, 0.34611706f}, {-0.93590593f, 0.35225005f},
+{-0.93358043f, 0.35836795f}, {-0.93121493f, 0.36447050f},
+{-0.92880955f, 0.37055744f}, {-0.92636438f, 0.37662850f},
+{-0.92387953f, 0.38268343f}, {-0.92135511f, 0.38872197f},
+{-0.91879121f, 0.39474386f}, {-0.91618796f, 0.40074883f},
+{-0.91354546f, 0.40673664f}, {-0.91086382f, 0.41270703f},
+{-0.90814317f, 0.41865974f}, {-0.90538362f, 0.42459451f},
+{-0.90258528f, 0.43051110f}, {-0.89974828f, 0.43640924f},
+{-0.89687274f, 0.44228869f}, {-0.89395878f, 0.44814919f},
+{-0.89100652f, 0.45399050f}, {-0.88801610f, 0.45981236f},
+{-0.88498764f, 0.46561452f}, {-0.88192126f, 0.47139674f},
+{-0.87881711f, 0.47715876f}, {-0.87567532f, 0.48290034f},
+{-0.87249601f, 0.48862124f}, {-0.86927932f, 0.49432121f},
+{-0.86602540f, 0.50000000f}, {-0.86273439f, 0.50565737f},
+{-0.85940641f, 0.51129309f}, {-0.85604162f, 0.51690690f},
+{-0.85264016f, 0.52249856f}, {-0.84920218f, 0.52806785f},
+{-0.84572782f, 0.53361452f}, {-0.84221723f, 0.53913832f},
+{-0.83867057f, 0.54463904f}, {-0.83508798f, 0.55011642f},
+{-0.83146961f, 0.55557023f}, {-0.82781563f, 0.56100025f},
+{-0.82412619f, 0.56640624f}, {-0.82040144f, 0.57178796f},
+{-0.81664156f, 0.57714519f}, {-0.81284668f, 0.58247770f},
+{-0.80901699f, 0.58778525f}, {-0.80515265f, 0.59306763f},
+{-0.80125381f, 0.59832460f}, {-0.79732065f, 0.60355594f},
+{-0.79335334f, 0.60876143f}, {-0.78935204f, 0.61394084f},
+{-0.78531693f, 0.61909395f}, {-0.78124818f, 0.62422054f},
+{-0.77714596f, 0.62932039f}, {-0.77301045f, 0.63439328f},
+{-0.76884183f, 0.63943900f}, {-0.76464028f, 0.64445733f},
+{-0.76040597f, 0.64944805f}, {-0.75613908f, 0.65441095f},
+{-0.75183981f, 0.65934582f}, {-0.74750833f, 0.66425244f},
+{-0.74314483f, 0.66913061f}, {-0.73874949f, 0.67398011f},
+{-0.73432251f, 0.67880075f}, {-0.72986407f, 0.68359230f},
+{-0.72537437f, 0.68835458f}, {-0.72085360f, 0.69308736f},
+{-0.71630194f, 0.69779046f}, {-0.71171961f, 0.70246367f},
+{-0.70710678f, 0.70710678f}, {-0.70246367f, 0.71171961f},
+{-0.69779046f, 0.71630194f}, {-0.69308736f, 0.72085360f},
+{-0.68835458f, 0.72537437f}, {-0.68359230f, 0.72986407f},
+{-0.67880075f, 0.73432251f}, {-0.67398011f, 0.73874949f},
+{-0.66913061f, 0.74314483f}, {-0.66425244f, 0.74750833f},
+{-0.65934582f, 0.75183981f}, {-0.65441095f, 0.75613908f},
+{-0.64944805f, 0.76040597f}, {-0.64445733f, 0.76464028f},
+{-0.63943900f, 0.76884183f}, {-0.63439328f, 0.77301045f},
+{-0.62932039f, 0.77714596f}, {-0.62422054f, 0.78124818f},
+{-0.61909395f, 0.78531693f}, {-0.61394084f, 0.78935204f},
+{-0.60876143f, 0.79335334f}, {-0.60355594f, 0.79732065f},
+{-0.59832460f, 0.80125381f}, {-0.59306763f, 0.80515265f},
+{-0.58778525f, 0.80901699f}, {-0.58247770f, 0.81284668f},
+{-0.57714519f, 0.81664156f}, {-0.57178796f, 0.82040144f},
+{-0.56640624f, 0.82412619f}, {-0.56100025f, 0.82781563f},
+{-0.55557023f, 0.83146961f}, {-0.55011642f, 0.83508798f},
+{-0.54463904f, 0.83867057f}, {-0.53913832f, 0.84221723f},
+{-0.53361452f, 0.84572782f}, {-0.52806785f, 0.84920218f},
+{-0.52249856f, 0.85264016f}, {-0.51690690f, 0.85604162f},
+{-0.51129309f, 0.85940641f}, {-0.50565737f, 0.86273439f},
+{-0.50000000f, 0.86602540f}, {-0.49432121f, 0.86927932f},
+{-0.48862124f, 0.87249601f}, {-0.48290034f, 0.87567532f},
+{-0.47715876f, 0.87881711f}, {-0.47139674f, 0.88192126f},
+{-0.46561452f, 0.88498764f}, {-0.45981236f, 0.88801610f},
+{-0.45399050f, 0.89100652f}, {-0.44814919f, 0.89395878f},
+{-0.44228869f, 0.89687274f}, {-0.43640924f, 0.89974828f},
+{-0.43051110f, 0.90258528f}, {-0.42459451f, 0.90538362f},
+{-0.41865974f, 0.90814317f}, {-0.41270703f, 0.91086382f},
+{-0.40673664f, 0.91354546f}, {-0.40074883f, 0.91618796f},
+{-0.39474386f, 0.91879121f}, {-0.38872197f, 0.92135511f},
+{-0.38268343f, 0.92387953f}, {-0.37662850f, 0.92636438f},
+{-0.37055744f, 0.92880955f}, {-0.36447050f, 0.93121493f},
+{-0.35836795f, 0.93358043f}, {-0.35225005f, 0.93590593f},
+{-0.34611706f, 0.93819134f}, {-0.33996924f, 0.94043656f},
+{-0.33380686f, 0.94264149f}, {-0.32763018f, 0.94480605f},
+{-0.32143947f, 0.94693013f}, {-0.31523498f, 0.94901365f},
+{-0.30901699f, 0.95105652f}, {-0.30278577f, 0.95305864f},
+{-0.29654157f, 0.95501994f}, {-0.29028468f, 0.95694034f},
+{-0.28401534f, 0.95881973f}, {-0.27773385f, 0.96065806f},
+{-0.27144045f, 0.96245524f}, {-0.26513543f, 0.96421118f},
+{-0.25881905f, 0.96592583f}, {-0.25249158f, 0.96759909f},
+{-0.24615329f, 0.96923091f}, {-0.23980446f, 0.97082121f},
+{-0.23344536f, 0.97236992f}, {-0.22707626f, 0.97387698f},
+{-0.22069744f, 0.97534232f}, {-0.21430915f, 0.97676588f},
+{-0.20791169f, 0.97814760f}, {-0.20150532f, 0.97948742f},
+{-0.19509032f, 0.98078528f}, {-0.18866696f, 0.98204113f},
+{-0.18223553f, 0.98325491f}, {-0.17579628f, 0.98442657f},
+{-0.16934950f, 0.98555606f}, {-0.16289547f, 0.98664333f},
+{-0.15643447f, 0.98768834f}, {-0.14996676f, 0.98869104f},
+{-0.14349262f, 0.98965139f}, {-0.13701234f, 0.99056934f},
+{-0.13052619f, 0.99144486f}, {-0.12403445f, 0.99227791f},
+{-0.11753740f, 0.99306846f}, {-0.11103531f, 0.99381646f},
+{-0.10452846f, 0.99452190f}, {-0.098017140f, 0.99518473f},
+{-0.091501619f, 0.99580493f}, {-0.084982177f, 0.99638247f},
+{-0.078459096f, 0.99691733f}, {-0.071932653f, 0.99740949f},
+{-0.065403129f, 0.99785892f}, {-0.058870804f, 0.99826561f},
+{-0.052335956f, 0.99862953f}, {-0.045798867f, 0.99895068f},
+{-0.039259816f, 0.99922904f}, {-0.032719083f, 0.99946459f},
+{-0.026176948f, 0.99965732f}, {-0.019633692f, 0.99980724f},
+{-0.013089596f, 0.99991433f}, {-0.0065449380f, 0.99997858f},
+{-1.8369702e-16f, 1.0000000f}, {0.0065449380f, 0.99997858f},
+{0.013089596f, 0.99991433f}, {0.019633692f, 0.99980724f},
+{0.026176948f, 0.99965732f}, {0.032719083f, 0.99946459f},
+{0.039259816f, 0.99922904f}, {0.045798867f, 0.99895068f},
+{0.052335956f, 0.99862953f}, {0.058870804f, 0.99826561f},
+{0.065403129f, 0.99785892f}, {0.071932653f, 0.99740949f},
+{0.078459096f, 0.99691733f}, {0.084982177f, 0.99638247f},
+{0.091501619f, 0.99580493f}, {0.098017140f, 0.99518473f},
+{0.10452846f, 0.99452190f}, {0.11103531f, 0.99381646f},
+{0.11753740f, 0.99306846f}, {0.12403445f, 0.99227791f},
+{0.13052619f, 0.99144486f}, {0.13701234f, 0.99056934f},
+{0.14349262f, 0.98965139f}, {0.14996676f, 0.98869104f},
+{0.15643447f, 0.98768834f}, {0.16289547f, 0.98664333f},
+{0.16934950f, 0.98555606f}, {0.17579628f, 0.98442657f},
+{0.18223553f, 0.98325491f}, {0.18866696f, 0.98204113f},
+{0.19509032f, 0.98078528f}, {0.20150532f, 0.97948742f},
+{0.20791169f, 0.97814760f}, {0.21430915f, 0.97676588f},
+{0.22069744f, 0.97534232f}, {0.22707626f, 0.97387698f},
+{0.23344536f, 0.97236992f}, {0.23980446f, 0.97082121f},
+{0.24615329f, 0.96923091f}, {0.25249158f, 0.96759909f},
+{0.25881905f, 0.96592583f}, {0.26513543f, 0.96421118f},
+{0.27144045f, 0.96245524f}, {0.27773385f, 0.96065806f},
+{0.28401534f, 0.95881973f}, {0.29028468f, 0.95694034f},
+{0.29654157f, 0.95501994f}, {0.30278577f, 0.95305864f},
+{0.30901699f, 0.95105652f}, {0.31523498f, 0.94901365f},
+{0.32143947f, 0.94693013f}, {0.32763018f, 0.94480605f},
+{0.33380686f, 0.94264149f}, {0.33996924f, 0.94043656f},
+{0.34611706f, 0.93819134f}, {0.35225005f, 0.93590593f},
+{0.35836795f, 0.93358043f}, {0.36447050f, 0.93121493f},
+{0.37055744f, 0.92880955f}, {0.37662850f, 0.92636438f},
+{0.38268343f, 0.92387953f}, {0.38872197f, 0.92135511f},
+{0.39474386f, 0.91879121f}, {0.40074883f, 0.91618796f},
+{0.40673664f, 0.91354546f}, {0.41270703f, 0.91086382f},
+{0.41865974f, 0.90814317f}, {0.42459451f, 0.90538362f},
+{0.43051110f, 0.90258528f}, {0.43640924f, 0.89974828f},
+{0.44228869f, 0.89687274f}, {0.44814919f, 0.89395878f},
+{0.45399050f, 0.89100652f}, {0.45981236f, 0.88801610f},
+{0.46561452f, 0.88498764f}, {0.47139674f, 0.88192126f},
+{0.47715876f, 0.87881711f}, {0.48290034f, 0.87567532f},
+{0.48862124f, 0.87249601f}, {0.49432121f, 0.86927932f},
+{0.50000000f, 0.86602540f}, {0.50565737f, 0.86273439f},
+{0.51129309f, 0.85940641f}, {0.51690690f, 0.85604162f},
+{0.52249856f, 0.85264016f}, {0.52806785f, 0.84920218f},
+{0.53361452f, 0.84572782f}, {0.53913832f, 0.84221723f},
+{0.54463904f, 0.83867057f}, {0.55011642f, 0.83508798f},
+{0.55557023f, 0.83146961f}, {0.56100025f, 0.82781563f},
+{0.56640624f, 0.82412619f}, {0.57178796f, 0.82040144f},
+{0.57714519f, 0.81664156f}, {0.58247770f, 0.81284668f},
+{0.58778525f, 0.80901699f}, {0.59306763f, 0.80515265f},
+{0.59832460f, 0.80125381f}, {0.60355594f, 0.79732065f},
+{0.60876143f, 0.79335334f}, {0.61394084f, 0.78935204f},
+{0.61909395f, 0.78531693f}, {0.62422054f, 0.78124818f},
+{0.62932039f, 0.77714596f}, {0.63439328f, 0.77301045f},
+{0.63943900f, 0.76884183f}, {0.64445733f, 0.76464028f},
+{0.64944805f, 0.76040597f}, {0.65441095f, 0.75613908f},
+{0.65934582f, 0.75183981f}, {0.66425244f, 0.74750833f},
+{0.66913061f, 0.74314483f}, {0.67398011f, 0.73874949f},
+{0.67880075f, 0.73432251f}, {0.68359230f, 0.72986407f},
+{0.68835458f, 0.72537437f}, {0.69308736f, 0.72085360f},
+{0.69779046f, 0.71630194f}, {0.70246367f, 0.71171961f},
+{0.70710678f, 0.70710678f}, {0.71171961f, 0.70246367f},
+{0.71630194f, 0.69779046f}, {0.72085360f, 0.69308736f},
+{0.72537437f, 0.68835458f}, {0.72986407f, 0.68359230f},
+{0.73432251f, 0.67880075f}, {0.73874949f, 0.67398011f},
+{0.74314483f, 0.66913061f}, {0.74750833f, 0.66425244f},
+{0.75183981f, 0.65934582f}, {0.75613908f, 0.65441095f},
+{0.76040597f, 0.64944805f}, {0.76464028f, 0.64445733f},
+{0.76884183f, 0.63943900f}, {0.77301045f, 0.63439328f},
+{0.77714596f, 0.62932039f}, {0.78124818f, 0.62422054f},
+{0.78531693f, 0.61909395f}, {0.78935204f, 0.61394084f},
+{0.79335334f, 0.60876143f}, {0.79732065f, 0.60355594f},
+{0.80125381f, 0.59832460f}, {0.80515265f, 0.59306763f},
+{0.80901699f, 0.58778525f}, {0.81284668f, 0.58247770f},
+{0.81664156f, 0.57714519f}, {0.82040144f, 0.57178796f},
+{0.82412619f, 0.56640624f}, {0.82781563f, 0.56100025f},
+{0.83146961f, 0.55557023f}, {0.83508798f, 0.55011642f},
+{0.83867057f, 0.54463904f}, {0.84221723f, 0.53913832f},
+{0.84572782f, 0.53361452f}, {0.84920218f, 0.52806785f},
+{0.85264016f, 0.52249856f}, {0.85604162f, 0.51690690f},
+{0.85940641f, 0.51129309f}, {0.86273439f, 0.50565737f},
+{0.86602540f, 0.50000000f}, {0.86927932f, 0.49432121f},
+{0.87249601f, 0.48862124f}, {0.87567532f, 0.48290034f},
+{0.87881711f, 0.47715876f}, {0.88192126f, 0.47139674f},
+{0.88498764f, 0.46561452f}, {0.88801610f, 0.45981236f},
+{0.89100652f, 0.45399050f}, {0.89395878f, 0.44814919f},
+{0.89687274f, 0.44228869f}, {0.89974828f, 0.43640924f},
+{0.90258528f, 0.43051110f}, {0.90538362f, 0.42459451f},
+{0.90814317f, 0.41865974f}, {0.91086382f, 0.41270703f},
+{0.91354546f, 0.40673664f}, {0.91618796f, 0.40074883f},
+{0.91879121f, 0.39474386f}, {0.92135511f, 0.38872197f},
+{0.92387953f, 0.38268343f}, {0.92636438f, 0.37662850f},
+{0.92880955f, 0.37055744f}, {0.93121493f, 0.36447050f},
+{0.93358043f, 0.35836795f}, {0.93590593f, 0.35225005f},
+{0.93819134f, 0.34611706f}, {0.94043656f, 0.33996924f},
+{0.94264149f, 0.33380686f}, {0.94480605f, 0.32763018f},
+{0.94693013f, 0.32143947f}, {0.94901365f, 0.31523498f},
+{0.95105652f, 0.30901699f}, {0.95305864f, 0.30278577f},
+{0.95501994f, 0.29654157f}, {0.95694034f, 0.29028468f},
+{0.95881973f, 0.28401534f}, {0.96065806f, 0.27773385f},
+{0.96245524f, 0.27144045f}, {0.96421118f, 0.26513543f},
+{0.96592583f, 0.25881905f}, {0.96759909f, 0.25249158f},
+{0.96923091f, 0.24615329f}, {0.97082121f, 0.23980446f},
+{0.97236992f, 0.23344536f}, {0.97387698f, 0.22707626f},
+{0.97534232f, 0.22069744f}, {0.97676588f, 0.21430915f},
+{0.97814760f, 0.20791169f}, {0.97948742f, 0.20150532f},
+{0.98078528f, 0.19509032f}, {0.98204113f, 0.18866696f},
+{0.98325491f, 0.18223553f}, {0.98442657f, 0.17579628f},
+{0.98555606f, 0.16934950f}, {0.98664333f, 0.16289547f},
+{0.98768834f, 0.15643447f}, {0.98869104f, 0.14996676f},
+{0.98965139f, 0.14349262f}, {0.99056934f, 0.13701234f},
+{0.99144486f, 0.13052619f}, {0.99227791f, 0.12403445f},
+{0.99306846f, 0.11753740f}, {0.99381646f, 0.11103531f},
+{0.99452190f, 0.10452846f}, {0.99518473f, 0.098017140f},
+{0.99580493f, 0.091501619f}, {0.99638247f, 0.084982177f},
+{0.99691733f, 0.078459096f}, {0.99740949f, 0.071932653f},
+{0.99785892f, 0.065403129f}, {0.99826561f, 0.058870804f},
+{0.99862953f, 0.052335956f}, {0.99895068f, 0.045798867f},
+{0.99922904f, 0.039259816f}, {0.99946459f, 0.032719083f},
+{0.99965732f, 0.026176948f}, {0.99980724f, 0.019633692f},
+{0.99991433f, 0.013089596f}, {0.99997858f, 0.0065449380f},
+};
+#ifndef FFT_BITREV960
+#define FFT_BITREV960
+static const opus_int16 fft_bitrev960[960] = {
+0, 192, 384, 576, 768, 64, 256, 448, 640, 832, 128, 320, 512, 704, 896,
+16, 208, 400, 592, 784, 80, 272, 464, 656, 848, 144, 336, 528, 720, 912,
+32, 224, 416, 608, 800, 96, 288, 480, 672, 864, 160, 352, 544, 736, 928,
+48, 240, 432, 624, 816, 112, 304, 496, 688, 880, 176, 368, 560, 752, 944,
+4, 196, 388, 580, 772, 68, 260, 452, 644, 836, 132, 324, 516, 708, 900,
+20, 212, 404, 596, 788, 84, 276, 468, 660, 852, 148, 340, 532, 724, 916,
+36, 228, 420, 612, 804, 100, 292, 484, 676, 868, 164, 356, 548, 740, 932,
+52, 244, 436, 628, 820, 116, 308, 500, 692, 884, 180, 372, 564, 756, 948,
+8, 200, 392, 584, 776, 72, 264, 456, 648, 840, 136, 328, 520, 712, 904,
+24, 216, 408, 600, 792, 88, 280, 472, 664, 856, 152, 344, 536, 728, 920,
+40, 232, 424, 616, 808, 104, 296, 488, 680, 872, 168, 360, 552, 744, 936,
+56, 248, 440, 632, 824, 120, 312, 504, 696, 888, 184, 376, 568, 760, 952,
+12, 204, 396, 588, 780, 76, 268, 460, 652, 844, 140, 332, 524, 716, 908,
+28, 220, 412, 604, 796, 92, 284, 476, 668, 860, 156, 348, 540, 732, 924,
+44, 236, 428, 620, 812, 108, 300, 492, 684, 876, 172, 364, 556, 748, 940,
+60, 252, 444, 636, 828, 124, 316, 508, 700, 892, 188, 380, 572, 764, 956,
+1, 193, 385, 577, 769, 65, 257, 449, 641, 833, 129, 321, 513, 705, 897,
+17, 209, 401, 593, 785, 81, 273, 465, 657, 849, 145, 337, 529, 721, 913,
+33, 225, 417, 609, 801, 97, 289, 481, 673, 865, 161, 353, 545, 737, 929,
+49, 241, 433, 625, 817, 113, 305, 497, 689, 881, 177, 369, 561, 753, 945,
+5, 197, 389, 581, 773, 69, 261, 453, 645, 837, 133, 325, 517, 709, 901,
+21, 213, 405, 597, 789, 85, 277, 469, 661, 853, 149, 341, 533, 725, 917,
+37, 229, 421, 613, 805, 101, 293, 485, 677, 869, 165, 357, 549, 741, 933,
+53, 245, 437, 629, 821, 117, 309, 501, 693, 885, 181, 373, 565, 757, 949,
+9, 201, 393, 585, 777, 73, 265, 457, 649, 841, 137, 329, 521, 713, 905,
+25, 217, 409, 601, 793, 89, 281, 473, 665, 857, 153, 345, 537, 729, 921,
+41, 233, 425, 617, 809, 105, 297, 489, 681, 873, 169, 361, 553, 745, 937,
+57, 249, 441, 633, 825, 121, 313, 505, 697, 889, 185, 377, 569, 761, 953,
+13, 205, 397, 589, 781, 77, 269, 461, 653, 845, 141, 333, 525, 717, 909,
+29, 221, 413, 605, 797, 93, 285, 477, 669, 861, 157, 349, 541, 733, 925,
+45, 237, 429, 621, 813, 109, 301, 493, 685, 877, 173, 365, 557, 749, 941,
+61, 253, 445, 637, 829, 125, 317, 509, 701, 893, 189, 381, 573, 765, 957,
+2, 194, 386, 578, 770, 66, 258, 450, 642, 834, 130, 322, 514, 706, 898,
+18, 210, 402, 594, 786, 82, 274, 466, 658, 850, 146, 338, 530, 722, 914,
+34, 226, 418, 610, 802, 98, 290, 482, 674, 866, 162, 354, 546, 738, 930,
+50, 242, 434, 626, 818, 114, 306, 498, 690, 882, 178, 370, 562, 754, 946,
+6, 198, 390, 582, 774, 70, 262, 454, 646, 838, 134, 326, 518, 710, 902,
+22, 214, 406, 598, 790, 86, 278, 470, 662, 854, 150, 342, 534, 726, 918,
+38, 230, 422, 614, 806, 102, 294, 486, 678, 870, 166, 358, 550, 742, 934,
+54, 246, 438, 630, 822, 118, 310, 502, 694, 886, 182, 374, 566, 758, 950,
+10, 202, 394, 586, 778, 74, 266, 458, 650, 842, 138, 330, 522, 714, 906,
+26, 218, 410, 602, 794, 90, 282, 474, 666, 858, 154, 346, 538, 730, 922,
+42, 234, 426, 618, 810, 106, 298, 490, 682, 874, 170, 362, 554, 746, 938,
+58, 250, 442, 634, 826, 122, 314, 506, 698, 890, 186, 378, 570, 762, 954,
+14, 206, 398, 590, 782, 78, 270, 462, 654, 846, 142, 334, 526, 718, 910,
+30, 222, 414, 606, 798, 94, 286, 478, 670, 862, 158, 350, 542, 734, 926,
+46, 238, 430, 622, 814, 110, 302, 494, 686, 878, 174, 366, 558, 750, 942,
+62, 254, 446, 638, 830, 126, 318, 510, 702, 894, 190, 382, 574, 766, 958,
+3, 195, 387, 579, 771, 67, 259, 451, 643, 835, 131, 323, 515, 707, 899,
+19, 211, 403, 595, 787, 83, 275, 467, 659, 851, 147, 339, 531, 723, 915,
+35, 227, 419, 611, 803, 99, 291, 483, 675, 867, 163, 355, 547, 739, 931,
+51, 243, 435, 627, 819, 115, 307, 499, 691, 883, 179, 371, 563, 755, 947,
+7, 199, 391, 583, 775, 71, 263, 455, 647, 839, 135, 327, 519, 711, 903,
+23, 215, 407, 599, 791, 87, 279, 471, 663, 855, 151, 343, 535, 727, 919,
+39, 231, 423, 615, 807, 103, 295, 487, 679, 871, 167, 359, 551, 743, 935,
+55, 247, 439, 631, 823, 119, 311, 503, 695, 887, 183, 375, 567, 759, 951,
+11, 203, 395, 587, 779, 75, 267, 459, 651, 843, 139, 331, 523, 715, 907,
+27, 219, 411, 603, 795, 91, 283, 475, 667, 859, 155, 347, 539, 731, 923,
+43, 235, 427, 619, 811, 107, 299, 491, 683, 875, 171, 363, 555, 747, 939,
+59, 251, 443, 635, 827, 123, 315, 507, 699, 891, 187, 379, 571, 763, 955,
+15, 207, 399, 591, 783, 79, 271, 463, 655, 847, 143, 335, 527, 719, 911,
+31, 223, 415, 607, 799, 95, 287, 479, 671, 863, 159, 351, 543, 735, 927,
+47, 239, 431, 623, 815, 111, 303, 495, 687, 879, 175, 367, 559, 751, 943,
+63, 255, 447, 639, 831, 127, 319, 511, 703, 895, 191, 383, 575, 767, 959,
+};
+#endif
+
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_0
+#define FFT_STATE96000_1920_0
+static const kiss_fft_state fft_state96000_1920_0 = {
+960,    /* nfft */
+0.0010416667f,    /* scale */
+-1,    /* shift */
+{5, 192, 3, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev960,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_960,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_1
+#define FFT_STATE96000_1920_1
+static const kiss_fft_state fft_state96000_1920_1 = {
+480,    /* nfft */
+0.0020833334f,    /* scale */
+1,    /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev480,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_2
+#define FFT_STATE96000_1920_2
+static const kiss_fft_state fft_state96000_1920_2 = {
+240,    /* nfft */
+0.0041666669f,    /* scale */
+2,    /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev240,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_3
+#define FFT_STATE96000_1920_3
+static const kiss_fft_state fft_state96000_1920_3 = {
+120,    /* nfft */
+0.0083333338f,    /* scale */
+3,    /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, },    /* factors */
+fft_bitrev120,    /* bitrev */
+fft_twiddles96000_1920,    /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES1920
+#define MDCT_TWIDDLES1920
+static const celt_coef mdct_twiddles1920[3600] = {
+0.99999998f, 0.99999831f, 0.99999396f, 0.99998693f, 0.99997722f,
+0.99996484f, 0.99994978f, 0.99993204f, 0.99991163f, 0.99988854f,
+0.99986277f, 0.99983433f, 0.99980320f, 0.99976941f, 0.99973293f,
+0.99969378f, 0.99965195f, 0.99960745f, 0.99956026f, 0.99951041f,
+0.99945787f, 0.99940267f, 0.99934478f, 0.99928422f, 0.99922099f,
+0.99915507f, 0.99908649f, 0.99901523f, 0.99894129f, 0.99886468f,
+0.99878540f, 0.99870344f, 0.99861881f, 0.99853150f, 0.99844153f,
+0.99834887f, 0.99825355f, 0.99815555f, 0.99805488f, 0.99795154f,
+0.99784553f, 0.99773684f, 0.99762548f, 0.99751146f, 0.99739476f,
+0.99727539f, 0.99715335f, 0.99702864f, 0.99690127f, 0.99677122f,
+0.99663850f, 0.99650312f, 0.99636507f, 0.99622435f, 0.99608096f,
+0.99593491f, 0.99578619f, 0.99563481f, 0.99548076f, 0.99532404f,
+0.99516466f, 0.99500261f, 0.99483790f, 0.99467053f, 0.99450050f,
+0.99432780f, 0.99415244f, 0.99397441f, 0.99379373f, 0.99361039f,
+0.99342438f, 0.99323572f, 0.99304440f, 0.99285041f, 0.99265377f,
+0.99245448f, 0.99225252f, 0.99204791f, 0.99184064f, 0.99163072f,
+0.99141814f, 0.99120291f, 0.99098503f, 0.99076449f, 0.99054130f,
+0.99031545f, 0.99008696f, 0.98985581f, 0.98962202f, 0.98938557f,
+0.98914648f, 0.98890474f, 0.98866035f, 0.98841331f, 0.98816363f,
+0.98791130f, 0.98765632f, 0.98739871f, 0.98713845f, 0.98687554f,
+0.98660999f, 0.98634181f, 0.98607098f, 0.98579751f, 0.98552140f,
+0.98524265f, 0.98496127f, 0.98467725f, 0.98439059f, 0.98410130f,
+0.98380937f, 0.98351481f, 0.98321761f, 0.98291779f, 0.98261533f,
+0.98231024f, 0.98200252f, 0.98169217f, 0.98137919f, 0.98106359f,
+0.98074536f, 0.98042450f, 0.98010102f, 0.97977491f, 0.97944619f,
+0.97911483f, 0.97878086f, 0.97844427f, 0.97810506f, 0.97776322f,
+0.97741878f, 0.97707171f, 0.97672203f, 0.97636973f, 0.97601482f,
+0.97565730f, 0.97529716f, 0.97493441f, 0.97456906f, 0.97420109f,
+0.97383051f, 0.97345733f, 0.97308154f, 0.97270315f, 0.97232215f,
+0.97193855f, 0.97155235f, 0.97116355f, 0.97077214f, 0.97037814f,
+0.96998154f, 0.96958234f, 0.96918054f, 0.96877615f, 0.96836917f,
+0.96795960f, 0.96754743f, 0.96713267f, 0.96671533f, 0.96629539f,
+0.96587287f, 0.96544776f, 0.96502007f, 0.96458979f, 0.96415693f,
+0.96372149f, 0.96328347f, 0.96284288f, 0.96239970f, 0.96195394f,
+0.96150562f, 0.96105471f, 0.96060124f, 0.96014519f, 0.95968657f,
+0.95922538f, 0.95876162f, 0.95829530f, 0.95782641f, 0.95735496f,
+0.95688094f, 0.95640437f, 0.95592523f, 0.95544353f, 0.95495927f,
+0.95447246f, 0.95398309f, 0.95349117f, 0.95299669f, 0.95249967f,
+0.95200009f, 0.95149797f, 0.95099329f, 0.95048607f, 0.94997631f,
+0.94946400f, 0.94894915f, 0.94843176f, 0.94791184f, 0.94738937f,
+0.94686437f, 0.94633683f, 0.94580676f, 0.94527415f, 0.94473902f,
+0.94420135f, 0.94366116f, 0.94311844f, 0.94257320f, 0.94202543f,
+0.94147514f, 0.94092233f, 0.94036700f, 0.93980916f, 0.93924879f,
+0.93868592f, 0.93812052f, 0.93755262f, 0.93698221f, 0.93640929f,
+0.93583386f, 0.93525593f, 0.93467549f, 0.93409255f, 0.93350711f,
+0.93291917f, 0.93232873f, 0.93173580f, 0.93114037f, 0.93054245f,
+0.92994204f, 0.92933913f, 0.92873374f, 0.92812587f, 0.92751550f,
+0.92690266f, 0.92628733f, 0.92566953f, 0.92504924f, 0.92442648f,
+0.92380124f, 0.92317353f, 0.92254335f, 0.92191070f, 0.92127558f,
+0.92063799f, 0.91999794f, 0.91935543f, 0.91871045f, 0.91806302f,
+0.91741313f, 0.91676078f, 0.91610597f, 0.91544872f, 0.91478901f,
+0.91412685f, 0.91346225f, 0.91279520f, 0.91212571f, 0.91145377f,
+0.91077939f, 0.91010258f, 0.90942333f, 0.90874164f, 0.90805753f,
+0.90737098f, 0.90668200f, 0.90599059f, 0.90529676f, 0.90460050f,
+0.90390183f, 0.90320073f, 0.90249721f, 0.90179128f, 0.90108293f,
+0.90037218f, 0.89965901f, 0.89894343f, 0.89822544f, 0.89750505f,
+0.89678226f, 0.89605707f, 0.89532948f, 0.89459949f, 0.89386710f,
+0.89313232f, 0.89239515f, 0.89165560f, 0.89091365f, 0.89016932f,
+0.88942261f, 0.88867351f, 0.88792204f, 0.88716818f, 0.88641196f,
+0.88565336f, 0.88489239f, 0.88412905f, 0.88336334f, 0.88259527f,
+0.88182483f, 0.88105203f, 0.88027688f, 0.87949937f, 0.87871950f,
+0.87793728f, 0.87715271f, 0.87636579f, 0.87557653f, 0.87478492f,
+0.87399097f, 0.87319468f, 0.87239605f, 0.87159509f, 0.87079179f,
+0.86998616f, 0.86917820f, 0.86836792f, 0.86755531f, 0.86674037f,
+0.86592312f, 0.86510355f, 0.86428166f, 0.86345746f, 0.86263095f,
+0.86180212f, 0.86097099f, 0.86013756f, 0.85930182f, 0.85846378f,
+0.85762344f, 0.85678081f, 0.85593588f, 0.85508866f, 0.85423915f,
+0.85338736f, 0.85253328f, 0.85167692f, 0.85081827f, 0.84995735f,
+0.84909416f, 0.84822869f, 0.84736095f, 0.84649094f, 0.84561866f,
+0.84474412f, 0.84386732f, 0.84298826f, 0.84210695f, 0.84122337f,
+0.84033755f, 0.83944948f, 0.83855915f, 0.83766659f, 0.83677178f,
+0.83587473f, 0.83497544f, 0.83407392f, 0.83317016f, 0.83226418f,
+0.83135596f, 0.83044552f, 0.82953286f, 0.82861797f, 0.82770087f,
+0.82678155f, 0.82586002f, 0.82493628f, 0.82401032f, 0.82308217f,
+0.82215180f, 0.82121924f, 0.82028448f, 0.81934752f, 0.81840837f,
+0.81746703f, 0.81652349f, 0.81557778f, 0.81462988f, 0.81367979f,
+0.81272753f, 0.81177310f, 0.81081649f, 0.80985771f, 0.80889676f,
+0.80793364f, 0.80696837f, 0.80600093f, 0.80503133f, 0.80405958f,
+0.80308568f, 0.80210962f, 0.80113142f, 0.80015107f, 0.79916858f,
+0.79818396f, 0.79719719f, 0.79620829f, 0.79521726f, 0.79422410f,
+0.79322881f, 0.79223140f, 0.79123187f, 0.79023022f, 0.78922646f,
+0.78822058f, 0.78721259f, 0.78620249f, 0.78519029f, 0.78417599f,
+0.78315958f, 0.78214108f, 0.78112049f, 0.78009781f, 0.77907303f,
+0.77804617f, 0.77701723f, 0.77598621f, 0.77495311f, 0.77391793f,
+0.77288068f, 0.77184137f, 0.77079998f, 0.76975654f, 0.76871103f,
+0.76766347f, 0.76661384f, 0.76556217f, 0.76450845f, 0.76345268f,
+0.76239487f, 0.76133501f, 0.76027312f, 0.75920919f, 0.75814323f,
+0.75707524f, 0.75600522f, 0.75493318f, 0.75385911f, 0.75278303f,
+0.75170494f, 0.75062483f, 0.74954271f, 0.74845858f, 0.74737245f,
+0.74628432f, 0.74519419f, 0.74410207f, 0.74300795f, 0.74191185f,
+0.74081376f, 0.73971368f, 0.73861163f, 0.73750759f, 0.73640158f,
+0.73529361f, 0.73418366f, 0.73307175f, 0.73195787f, 0.73084203f,
+0.72972424f, 0.72860450f, 0.72748280f, 0.72635916f, 0.72523357f,
+0.72410604f, 0.72297657f, 0.72184516f, 0.72071182f, 0.71957656f,
+0.71843936f, 0.71730025f, 0.71615921f, 0.71501625f, 0.71387138f,
+0.71272460f, 0.71157592f, 0.71042532f, 0.70927283f, 0.70811843f,
+0.70696214f, 0.70580396f, 0.70464389f, 0.70348193f, 0.70231808f,
+0.70115236f, 0.69998476f, 0.69881528f, 0.69764394f, 0.69647073f,
+0.69529565f, 0.69411871f, 0.69293991f, 0.69175926f, 0.69057675f,
+0.68939240f, 0.68820620f, 0.68701816f, 0.68582828f, 0.68463656f,
+0.68344301f, 0.68224763f, 0.68105042f, 0.67985139f, 0.67865054f,
+0.67744787f, 0.67624339f, 0.67503710f, 0.67382900f, 0.67261910f,
+0.67140739f, 0.67019389f, 0.66897860f, 0.66776151f, 0.66654264f,
+0.66532198f, 0.66409954f, 0.66287532f, 0.66164932f, 0.66042156f,
+0.65919203f, 0.65796073f, 0.65672767f, 0.65549285f, 0.65425628f,
+0.65301796f, 0.65177788f, 0.65053607f, 0.64929251f, 0.64804721f,
+0.64680018f, 0.64555141f, 0.64430092f, 0.64304871f, 0.64179477f,
+0.64053911f, 0.63928174f, 0.63802265f, 0.63676186f, 0.63549936f,
+0.63423517f, 0.63296927f, 0.63170168f, 0.63043240f, 0.62916143f,
+0.62788877f, 0.62661444f, 0.62533842f, 0.62406074f, 0.62278138f,
+0.62150035f, 0.62021766f, 0.61893331f, 0.61764731f, 0.61635965f,
+0.61507034f, 0.61377938f, 0.61248678f, 0.61119254f, 0.60989666f,
+0.60859915f, 0.60730001f, 0.60599925f, 0.60469686f, 0.60339285f,
+0.60208723f, 0.60078000f, 0.59947115f, 0.59816071f, 0.59684866f,
+0.59553501f, 0.59421977f, 0.59290294f, 0.59158452f, 0.59026452f,
+0.58894293f, 0.58761977f, 0.58629504f, 0.58496873f, 0.58364086f,
+0.58231143f, 0.58098044f, 0.57964789f, 0.57831380f, 0.57697815f,
+0.57564096f, 0.57430223f, 0.57296196f, 0.57162015f, 0.57027682f,
+0.56893195f, 0.56758557f, 0.56623767f, 0.56488825f, 0.56353731f,
+0.56218487f, 0.56083093f, 0.55947548f, 0.55811853f, 0.55676009f,
+0.55540016f, 0.55403874f, 0.55267584f, 0.55131146f, 0.54994560f,
+0.54857827f, 0.54720948f, 0.54583921f, 0.54446749f, 0.54309431f,
+0.54171967f, 0.54034359f, 0.53896605f, 0.53758708f, 0.53620666f,
+0.53482481f, 0.53344153f, 0.53205682f, 0.53067068f, 0.52928312f,
+0.52789415f, 0.52650377f, 0.52511197f, 0.52371877f, 0.52232416f,
+0.52092816f, 0.51953076f, 0.51813197f, 0.51673180f, 0.51533024f,
+0.51392730f, 0.51252299f, 0.51111730f, 0.50971025f, 0.50830183f,
+0.50689204f, 0.50548091f, 0.50406842f, 0.50265458f, 0.50123939f,
+0.49982286f, 0.49840499f, 0.49698579f, 0.49556526f, 0.49414340f,
+0.49272022f, 0.49129572f, 0.48986991f, 0.48844278f, 0.48701434f,
+0.48558461f, 0.48415357f, 0.48272123f, 0.48128760f, 0.47985269f,
+0.47841649f, 0.47697901f, 0.47554025f, 0.47410021f, 0.47265891f,
+0.47121635f, 0.46977252f, 0.46832743f, 0.46688109f, 0.46543350f,
+0.46398467f, 0.46253459f, 0.46108327f, 0.45963072f, 0.45817694f,
+0.45672193f, 0.45526570f, 0.45380825f, 0.45234959f, 0.45088971f,
+0.44942863f, 0.44796634f, 0.44650286f, 0.44503818f, 0.44357230f,
+0.44210524f, 0.44063700f, 0.43916758f, 0.43769698f, 0.43622521f,
+0.43475227f, 0.43327816f, 0.43180290f, 0.43032648f, 0.42884891f,
+0.42737019f, 0.42589033f, 0.42440932f, 0.42292718f, 0.42144391f,
+0.41995951f, 0.41847399f, 0.41698734f, 0.41549958f, 0.41401070f,
+0.41252072f, 0.41102963f, 0.40953745f, 0.40804416f, 0.40654979f,
+0.40505432f, 0.40355777f, 0.40206014f, 0.40056144f, 0.39906166f,
+0.39756081f, 0.39605890f, 0.39455593f, 0.39305190f, 0.39154682f,
+0.39004069f, 0.38853352f, 0.38702530f, 0.38551605f, 0.38400577f,
+0.38249446f, 0.38098213f, 0.37946878f, 0.37795441f, 0.37643902f,
+0.37492263f, 0.37340524f, 0.37188685f, 0.37036746f, 0.36884708f,
+0.36732571f, 0.36580336f, 0.36428003f, 0.36275572f, 0.36123045f,
+0.35970420f, 0.35817700f, 0.35664883f, 0.35511971f, 0.35358964f,
+0.35205862f, 0.35052666f, 0.34899376f, 0.34745992f, 0.34592516f,
+0.34438947f, 0.34285286f, 0.34131533f, 0.33977688f, 0.33823753f,
+0.33669727f, 0.33515611f, 0.33361405f, 0.33207110f, 0.33052726f,
+0.32898254f, 0.32743693f, 0.32589045f, 0.32434309f, 0.32279487f,
+0.32124578f, 0.31969583f, 0.31814503f, 0.31659338f, 0.31504087f,
+0.31348753f, 0.31193334f, 0.31037832f, 0.30882247f, 0.30726579f,
+0.30570829f, 0.30414997f, 0.30259083f, 0.30103089f, 0.29947014f,
+0.29790859f, 0.29634624f, 0.29478309f, 0.29321916f, 0.29165445f,
+0.29008895f, 0.28852267f, 0.28695563f, 0.28538781f, 0.28381923f,
+0.28224989f, 0.28067980f, 0.27910895f, 0.27753736f, 0.27596502f,
+0.27439194f, 0.27281813f, 0.27124359f, 0.26966833f, 0.26809234f,
+0.26651563f, 0.26493821f, 0.26336008f, 0.26178125f, 0.26020171f,
+0.25862148f, 0.25704055f, 0.25545894f, 0.25387664f, 0.25229367f,
+0.25071002f, 0.24912569f, 0.24754070f, 0.24595505f, 0.24436874f,
+0.24278177f, 0.24119416f, 0.23960590f, 0.23801699f, 0.23642745f,
+0.23483728f, 0.23324648f, 0.23165505f, 0.23006301f, 0.22847034f,
+0.22687707f, 0.22528319f, 0.22368870f, 0.22209362f, 0.22049794f,
+0.21890167f, 0.21730482f, 0.21570738f, 0.21410937f, 0.21251078f,
+0.21091163f, 0.20931191f, 0.20771163f, 0.20611079f, 0.20450940f,
+0.20290746f, 0.20130498f, 0.19970196f, 0.19809841f, 0.19649433f,
+0.19488972f, 0.19328459f, 0.19167894f, 0.19007277f, 0.18846610f,
+0.18685893f, 0.18525125f, 0.18364308f, 0.18203442f, 0.18042526f,
+0.17881563f, 0.17720552f, 0.17559493f, 0.17398387f, 0.17237235f,
+0.17076037f, 0.16914792f, 0.16753503f, 0.16592169f, 0.16430790f,
+0.16269367f, 0.16107901f, 0.15946391f, 0.15784839f, 0.15623245f,
+0.15461609f, 0.15299931f, 0.15138213f, 0.14976453f, 0.14814654f,
+0.14652815f, 0.14490937f, 0.14329020f, 0.14167065f, 0.14005072f,
+0.13843041f, 0.13680974f, 0.13518869f, 0.13356729f, 0.13194552f,
+0.13032341f, 0.12870094f, 0.12707813f, 0.12545498f, 0.12383150f,
+0.12220768f, 0.12058354f, 0.11895907f, 0.11733428f, 0.11570918f,
+0.11408377f, 0.11245806f, 0.11083204f, 0.10920573f, 0.10757912f,
+0.10595223f, 0.10432505f, 0.10269759f, 0.10106986f, 0.099441861f,
+0.097813592f, 0.096185062f, 0.094556275f, 0.092927234f, 0.091297944f,
+0.089668410f, 0.088038636f, 0.086408626f, 0.084778385f, 0.083147917f,
+0.081517226f, 0.079886317f, 0.078255194f, 0.076623861f, 0.074992324f,
+0.073360585f, 0.071728651f, 0.070096524f, 0.068464209f, 0.066831712f,
+0.065199035f, 0.063566184f, 0.061933162f, 0.060299975f, 0.058666626f,
+0.057033121f, 0.055399462f, 0.053765655f, 0.052131705f, 0.050497614f,
+0.048863389f, 0.047229033f, 0.045594550f, 0.043959945f, 0.042325222f,
+0.040690387f, 0.039055442f, 0.037420393f, 0.035785243f, 0.034149998f,
+0.032514661f, 0.030879237f, 0.029243731f, 0.027608146f, 0.025972487f,
+0.024336759f, 0.022700965f, 0.021065111f, 0.019429201f, 0.017793238f,
+0.016157228f, 0.014521174f, 0.012885082f, 0.011248955f, 0.0096127982f,
+0.0079766155f, 0.0063404114f, 0.0047041904f, 0.0030679568f, 0.0014317149f,
+-0.00020453077f, -0.0018407759f, -0.0034770161f, -0.0051132470f, -0.0067494642f,
+-0.0083856634f, -0.010021840f, -0.011657990f, -0.013294109f, -0.014930192f,
+-0.016566235f, -0.018202233f, -0.019838183f, -0.021474080f, -0.023109920f,
+-0.024745697f, -0.026381408f, -0.028017049f, -0.029652615f, -0.031288101f,
+-0.032923503f, -0.034558818f, -0.036194040f, -0.037829164f, -0.039464188f,
+-0.041099106f, -0.042733914f, -0.044368607f, -0.046003182f, -0.047637634f,
+-0.049271958f, -0.050906150f, -0.052540206f, -0.054174121f, -0.055807891f,
+-0.057441512f, -0.059074978f, -0.060708287f, -0.062341433f, -0.063974413f,
+-0.065607221f, -0.067239853f, -0.068872305f, -0.070504573f, -0.072136653f,
+-0.073768539f, -0.075400227f, -0.077031714f, -0.078662994f, -0.080294064f,
+-0.081924919f, -0.083555555f, -0.085185966f, -0.086816150f, -0.088446102f,
+-0.090075816f, -0.091705289f, -0.093334517f, -0.094963495f, -0.096592219f,
+-0.098220684f, -0.099848886f, -0.10147682f, -0.10310448f, -0.10473187f,
+-0.10635898f, -0.10798580f, -0.10961233f, -0.11123857f, -0.11286451f,
+-0.11449015f, -0.11611549f, -0.11774051f, -0.11936521f, -0.12098960f,
+-0.12261367f, -0.12423740f, -0.12586080f, -0.12748387f, -0.12910659f,
+-0.13072897f, -0.13235100f, -0.13397267f, -0.13559399f, -0.13721494f,
+-0.13883553f, -0.14045574f, -0.14207558f, -0.14369503f, -0.14531411f,
+-0.14693279f, -0.14855108f, -0.15016897f, -0.15178646f, -0.15340354f,
+-0.15502022f, -0.15663647f, -0.15825231f, -0.15986773f, -0.16148271f,
+-0.16309727f, -0.16471139f, -0.16632506f, -0.16793829f, -0.16955108f,
+-0.17116340f, -0.17277527f, -0.17438668f, -0.17599762f, -0.17760809f,
+-0.17921808f, -0.18082760f, -0.18243663f, -0.18404517f, -0.18565322f,
+-0.18726077f, -0.18886782f, -0.19047436f, -0.19208040f, -0.19368592f,
+-0.19529092f, -0.19689540f, -0.19849935f, -0.20010277f, -0.20170565f,
+-0.20330800f, -0.20490980f, -0.20651105f, -0.20811175f, -0.20971189f,
+-0.21131147f, -0.21291048f, -0.21450893f, -0.21610680f, -0.21770409f,
+-0.21930080f, -0.22089692f, -0.22249245f, -0.22408738f, -0.22568172f,
+-0.22727545f, -0.22886857f, -0.23046108f, -0.23205297f, -0.23364424f,
+-0.23523488f, -0.23682490f, -0.23841428f, -0.24000302f, -0.24159112f,
+-0.24317858f, -0.24476538f, -0.24635153f, -0.24793701f, -0.24952184f,
+-0.25110599f, -0.25268948f, -0.25427228f, -0.25585441f, -0.25743585f,
+-0.25901660f, -0.26059666f, -0.26217602f, -0.26375468f, -0.26533263f,
+-0.26690987f, -0.26848640f, -0.27006221f, -0.27163730f, -0.27321165f,
+-0.27478528f, -0.27635817f, -0.27793032f, -0.27950173f, -0.28107239f,
+-0.28264230f, -0.28421145f, -0.28577984f, -0.28734746f, -0.28891431f,
+-0.29048039f, -0.29204570f, -0.29361022f, -0.29517395f, -0.29673690f,
+-0.29829905f, -0.29986040f, -0.30142095f, -0.30298069f, -0.30453962f,
+-0.30609774f, -0.30765504f, -0.30921151f, -0.31076715f, -0.31232197f,
+-0.31387594f, -0.31542908f, -0.31698137f, -0.31853281f, -0.32008340f,
+-0.32163313f, -0.32318201f, -0.32473001f, -0.32627715f, -0.32782341f,
+-0.32936880f, -0.33091330f, -0.33245692f, -0.33399965f, -0.33554149f,
+-0.33708242f, -0.33862245f, -0.34016158f, -0.34169980f, -0.34323710f,
+-0.34477348f, -0.34630894f, -0.34784347f, -0.34937707f, -0.35090974f,
+-0.35244146f, -0.35397224f, -0.35550208f, -0.35703096f, -0.35855889f,
+-0.36008585f, -0.36161186f, -0.36313689f, -0.36466095f, -0.36618404f,
+-0.36770615f, -0.36922727f, -0.37074740f, -0.37226654f, -0.37378468f,
+-0.37530183f, -0.37681796f, -0.37833309f, -0.37984721f, -0.38136031f,
+-0.38287239f, -0.38438344f, -0.38589346f, -0.38740245f, -0.38891041f,
+-0.39041732f, -0.39192319f, -0.39342800f, -0.39493177f, -0.39643448f,
+-0.39793612f, -0.39943670f, -0.40093621f, -0.40243465f, -0.40393201f,
+-0.40542829f, -0.40692348f, -0.40841759f, -0.40991060f, -0.41140251f,
+-0.41289332f, -0.41438303f, -0.41587162f, -0.41735911f, -0.41884547f,
+-0.42033072f, -0.42181484f, -0.42329782f, -0.42477968f, -0.42626040f,
+-0.42773998f, -0.42921841f, -0.43069569f, -0.43217182f, -0.43364680f,
+-0.43512061f, -0.43659326f, -0.43806474f, -0.43953504f, -0.44100417f,
+-0.44247212f, -0.44393888f, -0.44540446f, -0.44686884f, -0.44833203f,
+-0.44979401f, -0.45125479f, -0.45271437f, -0.45417273f, -0.45562987f,
+-0.45708580f, -0.45854050f, -0.45999398f, -0.46144622f, -0.46289723f,
+-0.46434699f, -0.46579552f, -0.46724280f, -0.46868882f, -0.47013359f,
+-0.47157711f, -0.47301936f, -0.47446034f, -0.47590006f, -0.47733850f,
+-0.47877566f, -0.48021154f, -0.48164613f, -0.48307944f, -0.48451145f,
+-0.48594216f, -0.48737158f, -0.48879968f, -0.49022648f, -0.49165197f,
+-0.49307614f, -0.49449899f, -0.49592052f, -0.49734072f, -0.49875959f,
+-0.50017712f, -0.50159331f, -0.50300816f, -0.50442167f, -0.50583382f,
+-0.50724462f, -0.50865406f, -0.51006214f, -0.51146885f, -0.51287419f,
+-0.51427817f, -0.51568076f, -0.51708197f, -0.51848180f, -0.51988024f,
+-0.52127729f, -0.52267294f, -0.52406720f, -0.52546005f, -0.52685149f,
+-0.52824153f, -0.52963015f, -0.53101735f, -0.53240313f, -0.53378748f,
+-0.53517041f, -0.53655190f, -0.53793196f, -0.53931057f, -0.54068774f,
+-0.54206347f, -0.54343774f, -0.54481056f, -0.54618192f, -0.54755181f,
+-0.54892024f, -0.55028721f, -0.55165269f, -0.55301671f, -0.55437924f,
+-0.55574028f, -0.55709984f, -0.55845791f, -0.55981448f, -0.56116955f,
+-0.56252312f, -0.56387519f, -0.56522574f, -0.56657478f, -0.56792231f,
+-0.56926831f, -0.57061279f, -0.57195575f, -0.57329717f, -0.57463705f,
+-0.57597540f, -0.57731221f, -0.57864747f, -0.57998118f, -0.58131334f,
+-0.58264394f, -0.58397298f, -0.58530046f, -0.58662637f, -0.58795071f,
+-0.58927348f, -0.59059466f, -0.59191427f, -0.59323230f, -0.59454873f,
+-0.59586357f, -0.59717682f, -0.59848847f, -0.59979852f, -0.60110696f,
+-0.60241379f, -0.60371901f, -0.60502261f, -0.60632459f, -0.60762495f,
+-0.60892368f, -0.61022078f, -0.61151625f, -0.61281008f, -0.61410227f,
+-0.61539282f, -0.61668172f, -0.61796896f, -0.61925456f, -0.62053849f,
+-0.62182077f, -0.62310138f, -0.62438032f, -0.62565759f, -0.62693318f,
+-0.62820709f, -0.62947933f, -0.63074988f, -0.63201874f, -0.63328590f,
+-0.63455138f, -0.63581515f, -0.63707722f, -0.63833758f, -0.63959624f,
+-0.64085318f, -0.64210841f, -0.64336192f, -0.64461371f, -0.64586377f,
+-0.64711210f, -0.64835870f, -0.64960356f, -0.65084668f, -0.65208807f,
+-0.65332770f, -0.65456559f, -0.65580172f, -0.65703610f, -0.65826872f,
+-0.65949958f, -0.66072867f, -0.66195599f, -0.66318154f, -0.66440531f,
+-0.66562731f, -0.66684752f, -0.66806595f, -0.66928259f, -0.67049744f,
+-0.67171049f, -0.67292174f, -0.67413119f, -0.67533884f, -0.67654468f,
+-0.67774871f, -0.67895092f, -0.68015132f, -0.68134989f, -0.68254664f,
+-0.68374157f, -0.68493466f, -0.68612592f, -0.68731534f, -0.68850292f,
+-0.68968866f, -0.69087255f, -0.69205460f, -0.69323478f, -0.69441312f,
+-0.69558959f, -0.69676420f, -0.69793695f, -0.69910783f, -0.70027684f,
+-0.70144397f, -0.70260922f, -0.70377259f, -0.70493408f, -0.70609368f,
+-0.70725139f, -0.70840721f, -0.70956113f, -0.71071315f, -0.71186327f,
+-0.71301148f, -0.71415778f, -0.71530217f, -0.71644465f, -0.71758521f,
+-0.71872384f, -0.71986055f, -0.72099534f, -0.72212819f, -0.72325912f,
+-0.72438810f, -0.72551515f, -0.72664025f, -0.72776341f, -0.72888462f,
+-0.73000387f, -0.73112118f, -0.73223652f, -0.73334991f, -0.73446133f,
+-0.73557079f, -0.73667827f, -0.73778379f, -0.73888732f, -0.73998888f,
+-0.74108846f, -0.74218606f, -0.74328167f, -0.74437529f, -0.74546691f,
+-0.74655654f, -0.74764417f, -0.74872980f, -0.74981342f, -0.75089504f,
+-0.75197465f, -0.75305224f, -0.75412782f, -0.75520138f, -0.75627291f,
+-0.75734242f, -0.75840991f, -0.75947536f, -0.76053878f, -0.76160017f,
+-0.76265951f, -0.76371681f, -0.76477207f, -0.76582528f, -0.76687644f,
+-0.76792555f, -0.76897260f, -0.77001759f, -0.77106052f, -0.77210139f,
+-0.77314019f, -0.77417692f, -0.77521158f, -0.77624416f, -0.77727466f,
+-0.77830308f, -0.77932942f, -0.78035367f, -0.78137584f, -0.78239591f,
+-0.78341388f, -0.78442976f, -0.78544354f, -0.78645521f, -0.78746478f,
+-0.78847224f, -0.78947760f, -0.79048083f, -0.79148195f, -0.79248095f,
+-0.79347783f, -0.79447259f, -0.79546522f, -0.79645572f, -0.79744408f,
+-0.79843031f, -0.79941441f, -0.80039636f, -0.80137617f, -0.80235384f,
+-0.80332935f, -0.80430272f, -0.80527393f, -0.80624299f, -0.80720989f,
+-0.80817462f, -0.80913720f, -0.81009760f, -0.81105584f, -0.81201191f,
+-0.81296580f, -0.81391752f, -0.81486706f, -0.81581441f, -0.81675958f,
+-0.81770257f, -0.81864336f, -0.81958197f, -0.82051837f, -0.82145259f,
+-0.82238460f, -0.82331441f, -0.82424202f, -0.82516742f, -0.82609061f,
+-0.82701159f, -0.82793036f, -0.82884690f, -0.82976123f, -0.83067334f,
+-0.83158323f, -0.83249088f, -0.83339631f, -0.83429951f, -0.83520047f,
+-0.83609920f, -0.83699569f, -0.83788994f, -0.83878195f, -0.83967171f,
+-0.84055922f, -0.84144448f, -0.84232749f, -0.84320824f, -0.84408674f,
+-0.84496297f, -0.84583694f, -0.84670865f, -0.84757810f, -0.84844527f,
+-0.84931017f, -0.85017280f, -0.85103315f, -0.85189122f, -0.85274701f,
+-0.85360052f, -0.85445175f, -0.85530068f, -0.85614733f, -0.85699168f,
+-0.85783374f, -0.85867350f, -0.85951097f, -0.86034613f, -0.86117899f,
+-0.86200954f, -0.86283779f, -0.86366373f, -0.86448735f, -0.86530866f,
+-0.86612765f, -0.86694432f, -0.86775868f, -0.86857071f, -0.86938041f,
+-0.87018779f, -0.87099283f, -0.87179555f, -0.87259593f, -0.87339397f,
+-0.87418968f, -0.87498304f, -0.87577407f, -0.87656274f, -0.87734907f,
+-0.87813306f, -0.87891469f, -0.87969397f, -0.88047089f, -0.88124545f,
+-0.88201766f, -0.88278751f, -0.88355499f, -0.88432010f, -0.88508285f,
+-0.88584323f, -0.88660124f, -0.88735687f, -0.88811013f, -0.88886101f,
+-0.88960951f, -0.89035563f, -0.89109936f, -0.89184071f, -0.89257967f,
+-0.89331624f, -0.89405042f, -0.89478221f, -0.89551160f, -0.89623859f,
+-0.89696318f, -0.89768538f, -0.89840516f, -0.89912255f, -0.89983752f,
+-0.90055009f, -0.90126025f, -0.90196799f, -0.90267332f, -0.90337623f,
+-0.90407672f, -0.90477479f, -0.90547044f, -0.90616367f, -0.90685447f,
+-0.90754284f, -0.90822878f, -0.90891229f, -0.90959337f, -0.91027201f,
+-0.91094822f, -0.91162198f, -0.91229331f, -0.91296219f, -0.91362863f,
+-0.91429262f, -0.91495417f, -0.91561326f, -0.91626990f, -0.91692409f,
+-0.91757583f, -0.91822511f, -0.91887193f, -0.91951629f, -0.92015819f,
+-0.92079762f, -0.92143459f, -0.92206909f, -0.92270113f, -0.92333069f,
+-0.92395778f, -0.92458240f, -0.92520454f, -0.92582421f, -0.92644140f,
+-0.92705610f, -0.92766833f, -0.92827807f, -0.92888532f, -0.92949009f,
+-0.93009237f, -0.93069216f, -0.93128946f, -0.93188427f, -0.93247658f,
+-0.93306639f, -0.93365370f, -0.93423852f, -0.93482083f, -0.93540065f,
+-0.93597795f, -0.93655275f, -0.93712505f, -0.93769483f, -0.93826211f,
+-0.93882687f, -0.93938912f, -0.93994885f, -0.94050607f, -0.94106077f,
+-0.94161295f, -0.94216261f, -0.94270975f, -0.94325436f, -0.94379644f,
+-0.94433601f, -0.94487304f, -0.94540754f, -0.94593951f, -0.94646895f,
+-0.94699585f, -0.94752022f, -0.94804206f, -0.94856135f, -0.94907810f,
+-0.94959232f, -0.95010399f, -0.95061312f, -0.95111970f, -0.95162374f,
+-0.95212522f, -0.95262416f, -0.95312055f, -0.95361439f, -0.95410567f,
+-0.95459440f, -0.95508058f, -0.95556419f, -0.95604525f, -0.95652375f,
+-0.95699969f, -0.95747306f, -0.95794388f, -0.95841212f, -0.95887780f,
+-0.95934092f, -0.95980146f, -0.96025944f, -0.96071485f, -0.96116768f,
+-0.96161794f, -0.96206562f, -0.96251073f, -0.96295327f, -0.96339322f,
+-0.96383060f, -0.96426539f, -0.96469760f, -0.96512723f, -0.96555428f,
+-0.96597874f, -0.96640062f, -0.96681991f, -0.96723660f, -0.96765071f,
+-0.96806223f, -0.96847116f, -0.96887749f, -0.96928124f, -0.96968238f,
+-0.97008093f, -0.97047688f, -0.97087024f, -0.97126099f, -0.97164914f,
+-0.97203470f, -0.97241765f, -0.97279799f, -0.97317574f, -0.97355087f,
+-0.97392340f, -0.97429333f, -0.97466064f, -0.97502535f, -0.97538744f,
+-0.97574692f, -0.97610379f, -0.97645805f, -0.97680969f, -0.97715872f,
+-0.97750513f, -0.97784893f, -0.97819010f, -0.97852866f, -0.97886460f,
+-0.97919792f, -0.97952861f, -0.97985669f, -0.98018214f, -0.98050496f,
+-0.98082516f, -0.98114274f, -0.98145768f, -0.98177000f, -0.98207970f,
+-0.98238676f, -0.98269119f, -0.98299299f, -0.98329216f, -0.98358870f,
+-0.98388260f, -0.98417387f, -0.98446250f, -0.98474850f, -0.98503186f,
+-0.98531259f, -0.98559068f, -0.98586612f, -0.98613893f, -0.98640910f,
+-0.98667663f, -0.98694151f, -0.98720376f, -0.98746336f, -0.98772032f,
+-0.98797463f, -0.98822630f, -0.98847532f, -0.98872169f, -0.98896542f,
+-0.98920650f, -0.98944493f, -0.98968071f, -0.98991385f, -0.99014433f,
+-0.99037216f, -0.99059734f, -0.99081987f, -0.99103975f, -0.99125697f,
+-0.99147154f, -0.99168345f, -0.99189271f, -0.99209931f, -0.99230326f,
+-0.99250455f, -0.99270318f, -0.99289916f, -0.99309248f, -0.99328313f,
+-0.99347113f, -0.99365647f, -0.99383915f, -0.99401917f, -0.99419653f,
+-0.99437122f, -0.99454325f, -0.99471262f, -0.99487933f, -0.99504337f,
+-0.99520475f, -0.99536347f, -0.99551952f, -0.99567290f, -0.99582362f,
+-0.99597167f, -0.99611706f, -0.99625978f, -0.99639983f, -0.99653722f,
+-0.99667193f, -0.99680398f, -0.99693336f, -0.99706007f, -0.99718411f,
+-0.99730548f, -0.99742418f, -0.99754021f, -0.99765357f, -0.99776426f,
+-0.99787228f, -0.99797763f, -0.99808030f, -0.99818030f, -0.99827763f,
+-0.99837229f, -0.99846427f, -0.99855358f, -0.99864022f, -0.99872418f,
+-0.99880547f, -0.99888409f, -0.99896003f, -0.99903329f, -0.99910389f,
+-0.99917180f, -0.99923705f, -0.99929961f, -0.99935950f, -0.99941672f,
+-0.99947126f, -0.99952312f, -0.99957231f, -0.99961882f, -0.99966266f,
+-0.99970382f, -0.99974230f, -0.99977811f, -0.99981124f, -0.99984169f,
+-0.99986946f, -0.99989456f, -0.99991698f, -0.99993673f, -0.99995380f,
+-0.99996819f, -0.99997990f, -0.99998894f, -0.99999529f, -0.99999898f,
+0.99999992f, 0.99999322f, 0.99997582f, 0.99994771f, 0.99990889f,
+0.99985936f, 0.99979913f, 0.99972818f, 0.99964653f, 0.99955418f,
+0.99945112f, 0.99933736f, 0.99921289f, 0.99907773f, 0.99893186f,
+0.99877530f, 0.99860804f, 0.99843009f, 0.99824144f, 0.99804211f,
+0.99783209f, 0.99761138f, 0.99737998f, 0.99713791f, 0.99688516f,
+0.99662173f, 0.99634763f, 0.99606285f, 0.99576741f, 0.99546131f,
+0.99514455f, 0.99481713f, 0.99447905f, 0.99413033f, 0.99377096f,
+0.99340095f, 0.99302029f, 0.99262901f, 0.99222709f, 0.99181455f,
+0.99139139f, 0.99095760f, 0.99051321f, 0.99005821f, 0.98959261f,
+0.98911641f, 0.98862961f, 0.98813223f, 0.98762427f, 0.98710573f,
+0.98657662f, 0.98603694f, 0.98548670f, 0.98492591f, 0.98435457f,
+0.98377269f, 0.98318028f, 0.98257734f, 0.98196387f, 0.98133989f,
+0.98070539f, 0.98006040f, 0.97940491f, 0.97873893f, 0.97806247f,
+0.97737554f, 0.97667813f, 0.97597027f, 0.97525196f, 0.97452320f,
+0.97378401f, 0.97303439f, 0.97227435f, 0.97150389f, 0.97072303f,
+0.96993178f, 0.96913014f, 0.96831812f, 0.96749573f, 0.96666298f,
+0.96581987f, 0.96496643f, 0.96410265f, 0.96322854f, 0.96234412f,
+0.96144939f, 0.96054437f, 0.95962906f, 0.95870347f, 0.95776762f,
+0.95682151f, 0.95586515f, 0.95489856f, 0.95392174f, 0.95293471f,
+0.95193746f, 0.95093003f, 0.94991241f, 0.94888462f, 0.94784667f,
+0.94679856f, 0.94574032f, 0.94467195f, 0.94359346f, 0.94250486f,
+0.94140618f, 0.94029741f, 0.93917857f, 0.93804967f, 0.93691073f,
+0.93576176f, 0.93460276f, 0.93343375f, 0.93225475f, 0.93106577f,
+0.92986681f, 0.92865789f, 0.92743903f, 0.92621024f, 0.92497153f,
+0.92372291f, 0.92246440f, 0.92119602f, 0.91991776f, 0.91862966f,
+0.91733172f, 0.91602395f, 0.91470637f, 0.91337900f, 0.91204185f,
+0.91069493f, 0.90933825f, 0.90797184f, 0.90659570f, 0.90520986f,
+0.90381432f, 0.90240910f, 0.90099422f, 0.89956969f, 0.89813553f,
+0.89669174f, 0.89523836f, 0.89377538f, 0.89230284f, 0.89082074f,
+0.88932910f, 0.88782793f, 0.88631726f, 0.88479710f, 0.88326746f,
+0.88172836f, 0.88017982f, 0.87862185f, 0.87705448f, 0.87547771f,
+0.87389156f, 0.87229606f, 0.87069121f, 0.86907704f, 0.86745357f,
+0.86582080f, 0.86417876f, 0.86252747f, 0.86086694f, 0.85919719f,
+0.85751824f, 0.85583010f, 0.85413281f, 0.85242636f, 0.85071078f,
+0.84898610f, 0.84725232f, 0.84550947f, 0.84375756f, 0.84199662f,
+0.84022666f, 0.83844771f, 0.83665977f, 0.83486287f, 0.83305704f,
+0.83124228f, 0.82941862f, 0.82758608f, 0.82574467f, 0.82389442f,
+0.82203535f, 0.82016748f, 0.81829082f, 0.81640540f, 0.81451123f,
+0.81260835f, 0.81069676f, 0.80877649f, 0.80684755f, 0.80490998f,
+0.80296379f, 0.80100899f, 0.79904562f, 0.79707370f, 0.79509323f,
+0.79310425f, 0.79110678f, 0.78910084f, 0.78708644f, 0.78506362f,
+0.78303239f, 0.78099277f, 0.77894479f, 0.77688847f, 0.77482382f,
+0.77275088f, 0.77066967f, 0.76858020f, 0.76648250f, 0.76437659f,
+0.76226250f, 0.76014024f, 0.75800984f, 0.75587132f, 0.75372471f,
+0.75157003f, 0.74940730f, 0.74723654f, 0.74505779f, 0.74287105f,
+0.74067635f, 0.73847373f, 0.73626320f, 0.73404478f, 0.73181850f,
+0.72958438f, 0.72734245f, 0.72509273f, 0.72283525f, 0.72057002f,
+0.71829708f, 0.71601644f, 0.71372814f, 0.71143220f, 0.70912863f,
+0.70681747f, 0.70449874f, 0.70217247f, 0.69983868f, 0.69749739f,
+0.69514863f, 0.69279243f, 0.69042881f, 0.68805780f, 0.68567941f,
+0.68329369f, 0.68090064f, 0.67850031f, 0.67609270f, 0.67367786f,
+0.67125580f, 0.66882656f, 0.66639015f, 0.66394661f, 0.66149595f,
+0.65903821f, 0.65657341f, 0.65410159f, 0.65162275f, 0.64913694f,
+0.64664418f, 0.64414449f, 0.64163790f, 0.63912444f, 0.63660414f,
+0.63407702f, 0.63154311f, 0.62900244f, 0.62645503f, 0.62390091f,
+0.62134011f, 0.61877265f, 0.61619857f, 0.61361789f, 0.61103064f,
+0.60843685f, 0.60583654f, 0.60322974f, 0.60061648f, 0.59799679f,
+0.59537069f, 0.59273822f, 0.59009940f, 0.58745427f, 0.58480284f,
+0.58214514f, 0.57948122f, 0.57681109f, 0.57413478f, 0.57145232f,
+0.56876374f, 0.56606907f, 0.56336834f, 0.56066158f, 0.55794881f,
+0.55523006f, 0.55250537f, 0.54977477f, 0.54703827f, 0.54429592f,
+0.54154774f, 0.53879376f, 0.53603401f, 0.53326852f, 0.53049731f,
+0.52772043f, 0.52493790f, 0.52214974f, 0.51935599f, 0.51655668f,
+0.51375184f, 0.51094149f, 0.50812568f, 0.50530442f, 0.50247775f,
+0.49964570f, 0.49680830f, 0.49396558f, 0.49111757f, 0.48826430f,
+0.48540580f, 0.48254210f, 0.47967323f, 0.47679923f, 0.47392012f,
+0.47103594f, 0.46814671f, 0.46525247f, 0.46235324f, 0.45944907f,
+0.45653997f, 0.45362599f, 0.45070714f, 0.44778347f, 0.44485501f,
+0.44192178f, 0.43898381f, 0.43604115f, 0.43309382f, 0.43014185f,
+0.42718527f, 0.42422412f, 0.42125842f, 0.41828822f, 0.41531353f,
+0.41233440f, 0.40935085f, 0.40636291f, 0.40337063f, 0.40037402f,
+0.39737313f, 0.39436798f, 0.39135861f, 0.38834505f, 0.38532733f,
+0.38230548f, 0.37927953f, 0.37624953f, 0.37321550f, 0.37017747f,
+0.36713547f, 0.36408955f, 0.36103972f, 0.35798603f, 0.35492850f,
+0.35186718f, 0.34880208f, 0.34573325f, 0.34266072f, 0.33958451f,
+0.33650468f, 0.33342123f, 0.33033422f, 0.32724367f, 0.32414961f,
+0.32105209f, 0.31795112f, 0.31484675f, 0.31173901f, 0.30862793f,
+0.30551354f, 0.30239588f, 0.29927499f, 0.29615089f, 0.29302362f,
+0.28989321f, 0.28675969f, 0.28362310f, 0.28048348f, 0.27734085f,
+0.27419526f, 0.27104672f, 0.26789529f, 0.26474098f, 0.26158384f,
+0.25842390f, 0.25526119f, 0.25209575f, 0.24892761f, 0.24575680f,
+0.24258336f, 0.23940732f, 0.23622872f, 0.23304759f, 0.22986396f,
+0.22667787f, 0.22348935f, 0.22029844f, 0.21710517f, 0.21390958f,
+0.21071169f, 0.20751155f, 0.20430919f, 0.20110463f, 0.19789793f,
+0.19468910f, 0.19147819f, 0.18826523f, 0.18505026f, 0.18183330f,
+0.17861439f, 0.17539357f, 0.17217088f, 0.16894634f, 0.16571999f,
+0.16249186f, 0.15926200f, 0.15603043f, 0.15279719f, 0.14956231f,
+0.14632583f, 0.14308778f, 0.13984820f, 0.13660713f, 0.13336459f,
+0.13012062f, 0.12687526f, 0.12362854f, 0.12038049f, 0.11713116f,
+0.11388057f, 0.11062877f, 0.10737578f, 0.10412163f, 0.10086638f,
+0.097610040f, 0.094352658f, 0.091094266f, 0.087834897f, 0.084574589f,
+0.081313374f, 0.078051289f, 0.074788367f, 0.071524645f, 0.068260157f,
+0.064994938f, 0.061729023f, 0.058462447f, 0.055195244f, 0.051927451f,
+0.048659101f, 0.045390231f, 0.042120874f, 0.038851066f, 0.035580842f,
+0.032310238f, 0.029039287f, 0.025768025f, 0.022496487f, 0.019224708f,
+0.015952723f, 0.012680568f, 0.0094082767f, 0.0061358846f, 0.0028634269f,
+-0.00040906153f, -0.0036815456f, -0.0069539902f, -0.010226360f, -0.013498621f,
+-0.016770737f, -0.020042673f, -0.023314395f, -0.026585867f, -0.029857055f,
+-0.033127923f, -0.036398436f, -0.039668559f, -0.042938257f, -0.046207495f,
+-0.049476239f, -0.052744453f, -0.056012102f, -0.059279151f, -0.062545565f,
+-0.065811309f, -0.069076349f, -0.072340649f, -0.075604174f, -0.078866890f,
+-0.082128761f, -0.085389752f, -0.088649829f, -0.091908956f, -0.095167100f,
+-0.098424224f, -0.10168029f, -0.10493528f, -0.10818913f, -0.11144183f,
+-0.11469334f, -0.11794361f, -0.12119263f, -0.12444034f, -0.12768673f,
+-0.13093174f, -0.13417536f, -0.13741753f, -0.14065824f, -0.14389744f,
+-0.14713510f, -0.15037118f, -0.15360565f, -0.15683848f, -0.16006962f,
+-0.16329906f, -0.16652674f, -0.16975264f, -0.17297673f, -0.17619896f,
+-0.17941930f, -0.18263772f, -0.18585419f, -0.18906866f, -0.19228112f,
+-0.19549151f, -0.19869981f, -0.20190598f, -0.20510998f, -0.20831180f,
+-0.21151138f, -0.21470869f, -0.21790371f, -0.22109639f, -0.22428671f,
+-0.22747462f, -0.23066010f, -0.23384310f, -0.23702361f, -0.24020157f,
+-0.24337696f, -0.24654975f, -0.24971989f, -0.25288736f, -0.25605213f,
+-0.25921415f, -0.26237339f, -0.26552983f, -0.26868342f, -0.27183413f,
+-0.27498193f, -0.27812679f, -0.28126867f, -0.28440754f, -0.28754336f,
+-0.29067610f, -0.29380573f, -0.29693221f, -0.30005551f, -0.30317560f,
+-0.30629245f, -0.30940601f, -0.31251626f, -0.31562316f, -0.31872668f,
+-0.32182679f, -0.32492345f, -0.32801664f, -0.33110631f, -0.33419243f,
+-0.33727497f, -0.34035391f, -0.34342920f, -0.34650081f, -0.34956871f,
+-0.35263286f, -0.35569324f, -0.35874981f, -0.36180254f, -0.36485139f,
+-0.36789634f, -0.37093735f, -0.37397438f, -0.37700741f, -0.38003640f,
+-0.38306132f, -0.38608214f, -0.38909883f, -0.39211135f, -0.39511967f,
+-0.39812375f, -0.40112358f, -0.40411910f, -0.40711031f, -0.41009715f,
+-0.41307959f, -0.41605762f, -0.41903119f, -0.42200027f, -0.42496483f,
+-0.42792484f, -0.43088027f, -0.43383109f, -0.43677726f, -0.43971875f,
+-0.44265553f, -0.44558757f, -0.44851484f, -0.45143731f, -0.45435494f,
+-0.45726770f, -0.46017557f, -0.46307851f, -0.46597650f, -0.46886949f,
+-0.47175746f, -0.47464038f, -0.47751821f, -0.48039093f, -0.48325851f,
+-0.48612091f, -0.48897811f, -0.49183006f, -0.49467676f, -0.49751815f,
+-0.50035422f, -0.50318492f, -0.50601024f, -0.50883014f, -0.51164459f,
+-0.51445356f, -0.51725703f, -0.52005495f, -0.52284730f, -0.52563406f,
+-0.52841518f, -0.53119065f, -0.53396043f, -0.53672449f, -0.53948280f,
+-0.54223533f, -0.54498206f, -0.54772295f, -0.55045797f, -0.55318710f,
+-0.55591031f, -0.55862756f, -0.56133883f, -0.56404409f, -0.56674331f,
+-0.56943646f, -0.57212351f, -0.57480443f, -0.57747920f, -0.58014778f,
+-0.58281015f, -0.58546628f, -0.58811614f, -0.59075970f, -0.59339694f,
+-0.59602782f, -0.59865231f, -0.60127040f, -0.60388204f, -0.60648722f,
+-0.60908591f, -0.61167807f, -0.61426368f, -0.61684271f, -0.61941514f,
+-0.62198093f, -0.62454007f, -0.62709251f, -0.62963824f, -0.63217722f,
+-0.63470944f, -0.63723486f, -0.63975345f, -0.64226519f, -0.64477006f,
+-0.64726802f, -0.64975905f, -0.65224312f, -0.65472020f, -0.65719027f,
+-0.65965331f, -0.66210928f, -0.66455816f, -0.66699992f, -0.66943454f,
+-0.67186199f, -0.67428225f, -0.67669528f, -0.67910107f, -0.68149959f,
+-0.68389080f, -0.68627470f, -0.68865124f, -0.69102041f, -0.69338218f,
+-0.69573652f, -0.69808341f, -0.70042283f, -0.70275474f, -0.70507913f,
+-0.70739597f, -0.70970524f, -0.71200690f, -0.71430093f, -0.71658732f,
+-0.71886604f, -0.72113705f, -0.72340034f, -0.72565589f, -0.72790366f,
+-0.73014364f, -0.73237580f, -0.73460012f, -0.73681657f, -0.73902513f,
+-0.74122577f, -0.74341848f, -0.74560322f, -0.74777998f, -0.74994874f,
+-0.75210946f, -0.75426212f, -0.75640671f, -0.75854320f, -0.76067157f,
+-0.76279178f, -0.76490383f, -0.76700769f, -0.76910334f, -0.77119075f,
+-0.77326989f, -0.77534076f, -0.77740333f, -0.77945757f, -0.78150346f,
+-0.78354098f, -0.78557011f, -0.78759083f, -0.78960312f, -0.79160694f,
+-0.79360229f, -0.79558915f, -0.79756748f, -0.79953727f, -0.80149850f,
+-0.80345114f, -0.80539518f, -0.80733060f, -0.80925737f, -0.81117547f,
+-0.81308489f, -0.81498559f, -0.81687757f, -0.81876081f, -0.82063527f,
+-0.82250095f, -0.82435781f, -0.82620585f, -0.82804505f, -0.82987537f,
+-0.83169681f, -0.83350933f, -0.83531294f, -0.83710760f, -0.83889329f,
+-0.84067000f, -0.84243770f, -0.84419639f, -0.84594603f, -0.84768662f,
+-0.84941812f, -0.85114053f, -0.85285383f, -0.85455799f, -0.85625300f,
+-0.85793884f, -0.85961549f, -0.86128294f, -0.86294116f, -0.86459014f,
+-0.86622986f, -0.86786031f, -0.86948146f, -0.87109330f, -0.87269581f,
+-0.87428898f, -0.87587278f, -0.87744720f, -0.87901223f, -0.88056784f,
+-0.88211402f, -0.88365076f, -0.88517803f, -0.88669582f, -0.88820412f,
+-0.88970290f, -0.89119216f, -0.89267187f, -0.89414203f, -0.89560260f,
+-0.89705359f, -0.89849497f, -0.89992673f, -0.90134885f, -0.90276131f,
+-0.90416411f, -0.90555723f, -0.90694065f, -0.90831436f, -0.90967833f,
+-0.91103257f, -0.91237705f, -0.91371176f, -0.91503669f, -0.91635181f,
+-0.91765712f, -0.91895261f, -0.92023825f, -0.92151404f, -0.92277996f,
+-0.92403600f, -0.92528214f, -0.92651837f, -0.92774468f, -0.92896106f,
+-0.93016748f, -0.93136395f, -0.93255044f, -0.93372694f, -0.93489345f,
+-0.93604994f, -0.93719641f, -0.93833284f, -0.93945922f, -0.94057555f,
+-0.94168180f, -0.94277796f, -0.94386403f, -0.94493999f, -0.94600583f,
+-0.94706154f, -0.94810711f, -0.94914252f, -0.95016777f, -0.95118284f,
+-0.95218773f, -0.95318242f, -0.95416690f, -0.95514117f, -0.95610520f,
+-0.95705900f, -0.95800255f, -0.95893583f, -0.95985885f, -0.96077159f,
+-0.96167404f, -0.96256619f, -0.96344803f, -0.96431956f, -0.96518076f,
+-0.96603162f, -0.96687213f, -0.96770230f, -0.96852209f, -0.96933152f,
+-0.97013057f, -0.97091922f, -0.97169748f, -0.97246533f, -0.97322277f,
+-0.97396979f, -0.97470637f, -0.97543252f, -0.97614822f, -0.97685347f,
+-0.97754825f, -0.97823257f, -0.97890641f, -0.97956977f, -0.98022263f,
+-0.98086500f, -0.98149687f, -0.98211822f, -0.98272906f, -0.98332937f,
+-0.98391915f, -0.98449840f, -0.98506710f, -0.98562525f, -0.98617285f,
+-0.98670988f, -0.98723635f, -0.98775225f, -0.98825757f, -0.98875230f,
+-0.98923645f, -0.98971000f, -0.99017295f, -0.99062530f, -0.99106704f,
+-0.99149817f, -0.99191868f, -0.99232857f, -0.99272783f, -0.99311645f,
+-0.99349445f, -0.99386180f, -0.99421851f, -0.99456457f, -0.99489998f,
+-0.99522474f, -0.99553884f, -0.99584227f, -0.99613505f, -0.99641715f,
+-0.99668858f, -0.99694934f, -0.99719943f, -0.99743883f, -0.99766756f,
+-0.99788559f, -0.99809295f, -0.99828961f, -0.99847558f, -0.99865086f,
+-0.99881544f, -0.99896933f, -0.99911252f, -0.99924501f, -0.99936680f,
+-0.99947789f, -0.99957827f, -0.99966795f, -0.99974692f, -0.99981519f,
+-0.99987275f, -0.99991960f, -0.99995574f, -0.99998118f, -0.99999590f,
+0.99999967f, 0.99997289f, 0.99990328f, 0.99979084f, 0.99963557f,
+0.99943748f, 0.99919658f, 0.99891288f, 0.99858638f, 0.99821711f,
+0.99780508f, 0.99735031f, 0.99685281f, 0.99631261f, 0.99572973f,
+0.99510420f, 0.99443605f, 0.99372529f, 0.99297196f, 0.99217610f,
+0.99133774f, 0.99045692f, 0.98953366f, 0.98856802f, 0.98756003f,
+0.98650973f, 0.98541718f, 0.98428242f, 0.98310549f, 0.98188645f,
+0.98062534f, 0.97932224f, 0.97797718f, 0.97659022f, 0.97516144f,
+0.97369088f, 0.97217861f, 0.97062469f, 0.96902920f, 0.96739220f,
+0.96571376f, 0.96399395f, 0.96223284f, 0.96043052f, 0.95858705f,
+0.95670253f, 0.95477702f, 0.95281061f, 0.95080338f, 0.94875543f,
+0.94666684f, 0.94453769f, 0.94236808f, 0.94015810f, 0.93790786f,
+0.93561743f, 0.93328693f, 0.93091644f, 0.92850608f, 0.92605595f,
+0.92356614f, 0.92103677f, 0.91846795f, 0.91585979f, 0.91321239f,
+0.91052587f, 0.90780035f, 0.90503595f, 0.90223277f, 0.89939095f,
+0.89651059f, 0.89359184f, 0.89063481f, 0.88763962f, 0.88460641f,
+0.88153531f, 0.87842644f, 0.87527995f, 0.87209596f, 0.86887462f,
+0.86561605f, 0.86232041f, 0.85898782f, 0.85561844f, 0.85221241f,
+0.84876987f, 0.84529098f, 0.84177587f, 0.83822471f, 0.83463763f,
+0.83101481f, 0.82735639f, 0.82366252f, 0.81993338f, 0.81616911f,
+0.81236987f, 0.80853584f, 0.80466718f, 0.80076404f, 0.79682660f,
+0.79285503f, 0.78884950f, 0.78481017f, 0.78073723f, 0.77663084f,
+0.77249118f, 0.76831844f, 0.76411277f, 0.75987438f, 0.75560344f,
+0.75130013f, 0.74696464f, 0.74259715f, 0.73819784f, 0.73376692f,
+0.72930457f, 0.72481097f, 0.72028632f, 0.71573083f, 0.71114467f,
+0.70652804f, 0.70188116f, 0.69720420f, 0.69249738f, 0.68776090f,
+0.68299495f, 0.67819975f, 0.67337550f, 0.66852240f, 0.66364066f,
+0.65873050f, 0.65379211f, 0.64882573f, 0.64383154f, 0.63880978f,
+0.63376065f, 0.62868438f, 0.62358117f, 0.61845126f, 0.61329485f,
+0.60811216f, 0.60290343f, 0.59766888f, 0.59240872f, 0.58712318f,
+0.58181249f, 0.57647688f, 0.57111658f, 0.56573181f, 0.56032281f,
+0.55488980f, 0.54943303f, 0.54395272f, 0.53844911f, 0.53292243f,
+0.52737292f, 0.52180083f, 0.51620638f, 0.51058981f, 0.50495138f,
+0.49929132f, 0.49360987f, 0.48790727f, 0.48218377f, 0.47643962f,
+0.47067506f, 0.46489034f, 0.45908570f, 0.45326139f, 0.44741768f,
+0.44155479f, 0.43567299f, 0.42977253f, 0.42385365f, 0.41791662f,
+0.41196169f, 0.40598911f, 0.39999914f, 0.39399204f, 0.38796806f,
+0.38192746f, 0.37587050f, 0.36979743f, 0.36370853f, 0.35760405f,
+0.35148424f, 0.34534939f, 0.33919973f, 0.33303555f, 0.32685710f,
+0.32066465f, 0.31445847f, 0.30823881f, 0.30200595f, 0.29576015f,
+0.28950169f, 0.28323082f, 0.27694782f, 0.27065295f, 0.26434649f,
+0.25802871f, 0.25169988f, 0.24536026f, 0.23901013f, 0.23264977f,
+0.22627944f, 0.21989941f, 0.21350997f, 0.20711138f, 0.20070391f,
+0.19428785f, 0.18786347f, 0.18143104f, 0.17499084f, 0.16854314f,
+0.16208822f, 0.15562636f, 0.14915783f, 0.14268292f, 0.13620189f,
+0.12971502f, 0.12322260f, 0.11672491f, 0.11022221f, 0.10371479f,
+0.097202924f, 0.090686897f, 0.084166986f, 0.077643468f, 0.071116625f,
+0.064586736f, 0.058054080f, 0.051518937f, 0.044981587f, 0.038442310f,
+0.031901387f, 0.025359097f, 0.018815721f, 0.012271538f, 0.0057268303f,
+-0.00081812300f, -0.0073630412f, -0.013907644f, -0.020451651f, -0.026994782f,
+-0.033536757f, -0.040077295f, -0.046616116f, -0.053152941f, -0.059687488f,
+-0.066219479f, -0.072748633f, -0.079274670f, -0.085797312f, -0.092316279f,
+-0.098831291f, -0.10534207f, -0.11184834f, -0.11834981f, -0.12484622f,
+-0.13133727f, -0.13782270f, -0.14430223f, -0.15077558f, -0.15724246f,
+-0.16370261f, -0.17015575f, -0.17660160f, -0.18303989f, -0.18947033f,
+-0.19589266f, -0.20230660f, -0.20871187f, -0.21510820f, -0.22149531f,
+-0.22787294f, -0.23424080f, -0.24059864f, -0.24694616f, -0.25328311f,
+-0.25960920f, -0.26592418f, -0.27222777f, -0.27851969f, -0.28479968f,
+-0.29106748f, -0.29732280f, -0.30356539f, -0.30979497f, -0.31601129f,
+-0.32221406f, -0.32840304f, -0.33457794f, -0.34073852f, -0.34688450f,
+-0.35301562f, -0.35913161f, -0.36523223f, -0.37131719f, -0.37738626f,
+-0.38343915f, -0.38947562f, -0.39549541f, -0.40149825f, -0.40748390f,
+-0.41345209f, -0.41940257f, -0.42533508f, -0.43124938f, -0.43714520f,
+-0.44302229f, -0.44888041f, -0.45471930f, -0.46053871f, -0.46633839f,
+-0.47211810f, -0.47787758f, -0.48361659f, -0.48933489f, -0.49503222f,
+-0.50070835f, -0.50636303f, -0.51199602f, -0.51760707f, -0.52319595f,
+-0.52876243f, -0.53430625f, -0.53982718f, -0.54532499f, -0.55079944f,
+-0.55625029f, -0.56167732f, -0.56708028f, -0.57245896f, -0.57781311f,
+-0.58314251f, -0.58844693f, -0.59372614f, -0.59897992f, -0.60420805f,
+-0.60941029f, -0.61458642f, -0.61973623f, -0.62485949f, -0.62995598f,
+-0.63502549f, -0.64006780f, -0.64508268f, -0.65006994f, -0.65502934f,
+-0.65996069f, -0.66486377f, -0.66973837f, -0.67458427f, -0.67940128f,
+-0.68418919f, -0.68894779f, -0.69367688f, -0.69837625f, -0.70304571f,
+-0.70768504f, -0.71229407f, -0.71687258f, -0.72142039f, -0.72593729f,
+-0.73042309f, -0.73487761f, -0.73930064f, -0.74369201f, -0.74805152f,
+-0.75237898f, -0.75667422f, -0.76093704f, -0.76516727f, -0.76936471f,
+-0.77352921f, -0.77766056f, -0.78175861f, -0.78582316f, -0.78985406f,
+-0.79385112f, -0.79781417f, -0.80174305f, -0.80563758f, -0.80949760f,
+-0.81332295f, -0.81711346f, -0.82086896f, -0.82458930f, -0.82827432f,
+-0.83192386f, -0.83553776f, -0.83911587f, -0.84265803f, -0.84616410f,
+-0.84963392f, -0.85306735f, -0.85646423f, -0.85982442f, -0.86314779f,
+-0.86643418f, -0.86968345f, -0.87289547f, -0.87607009f, -0.87920719f,
+-0.88230663f, -0.88536827f, -0.88839199f, -0.89137765f, -0.89432512f,
+-0.89723429f, -0.90010502f, -0.90293719f, -0.90573069f, -0.90848539f,
+-0.91120117f, -0.91387791f, -0.91651551f, -0.91911385f, -0.92167282f,
+-0.92419231f, -0.92667220f, -0.92911240f, -0.93151280f, -0.93387330f,
+-0.93619380f, -0.93847419f, -0.94071438f, -0.94291427f, -0.94507377f,
+-0.94719279f, -0.94927123f, -0.95130901f, -0.95330604f, -0.95526223f,
+-0.95717750f, -0.95905177f, -0.96088496f, -0.96267699f, -0.96442777f,
+-0.96613725f, -0.96780534f, -0.96943197f, -0.97101707f, -0.97256058f,
+-0.97406243f, -0.97552255f, -0.97694089f, -0.97831737f, -0.97965195f,
+-0.98094456f, -0.98219515f, -0.98340367f, -0.98457006f, -0.98569428f,
+-0.98677627f, -0.98781599f, -0.98881340f, -0.98976845f, -0.99068110f,
+-0.99155132f, -0.99237906f, -0.99316428f, -0.99390697f, -0.99460708f,
+-0.99526458f, -0.99587945f, -0.99645166f, -0.99698119f, -0.99746801f,
+-0.99791210f, -0.99831344f, -0.99867202f, -0.99898782f, -0.99926082f,
+-0.99949102f, -0.99967841f, -0.99982297f, -0.99992470f, -0.99998360f,
+0.99999866f, 0.99989157f, 0.99961315f, 0.99916346f, 0.99854256f,
+0.99775057f, 0.99678762f, 0.99565388f, 0.99434953f, 0.99287481f,
+0.99122996f, 0.98941527f, 0.98743105f, 0.98527764f, 0.98295541f,
+0.98046475f, 0.97780610f, 0.97497990f, 0.97198664f, 0.96882685f,
+0.96550104f, 0.96200980f, 0.95835373f, 0.95453345f, 0.95054962f,
+0.94640291f, 0.94209404f, 0.93762375f, 0.93299280f, 0.92820199f,
+0.92325213f, 0.91814408f, 0.91287871f, 0.90745693f, 0.90187965f,
+0.89614785f, 0.89026249f, 0.88422459f, 0.87803519f, 0.87169533f,
+0.86520612f, 0.85856866f, 0.85178409f, 0.84485357f, 0.83777828f,
+0.83055945f, 0.82319831f, 0.81569611f, 0.80805415f, 0.80027373f,
+0.79235620f, 0.78430289f, 0.77611520f, 0.76779452f, 0.75934229f,
+0.75075995f, 0.74204897f, 0.73321084f, 0.72424708f, 0.71515923f,
+0.70594883f, 0.69661748f, 0.68716676f, 0.67759830f, 0.66791374f,
+0.65811474f, 0.64820297f, 0.63818013f, 0.62804795f, 0.61780815f,
+0.60746249f, 0.59701275f, 0.58646072f, 0.57580819f, 0.56505701f,
+0.55420900f, 0.54326604f, 0.53222998f, 0.52110274f, 0.50988620f,
+0.49858230f, 0.48719297f, 0.47572016f, 0.46416584f, 0.45253199f,
+0.44082059f, 0.42903367f, 0.41717323f, 0.40524131f, 0.39323996f,
+0.38117123f, 0.36903718f, 0.35683990f, 0.34458148f, 0.33226402f,
+0.31988962f, 0.30746042f, 0.29497853f, 0.28244610f, 0.26986527f,
+0.25723821f, 0.24456706f, 0.23185402f, 0.21910124f, 0.20631092f,
+0.19348526f, 0.18062644f, 0.16773667f, 0.15481816f, 0.14187312f,
+0.12890377f, 0.11591234f, 0.10290104f, 0.089872115f, 0.076827789f,
+0.063770300f, 0.050701883f, 0.037624779f, 0.024541229f, 0.011453473f,
+-0.0016362454f, -0.014725683f, -0.027812598f, -0.040894747f, -0.053969889f,
+-0.067035784f, -0.080090192f, -0.093130877f, -0.10615561f, -0.11916214f,
+-0.13214826f, -0.14511174f, -0.15805036f, -0.17096189f, -0.18384413f,
+-0.19669487f, -0.20951190f, -0.22229304f, -0.23503609f, -0.24773886f,
+-0.26039919f, -0.27301490f, -0.28558383f, -0.29810383f, -0.31057274f,
+-0.32298845f, -0.33534881f, -0.34765171f, -0.35989504f, -0.37207670f,
+-0.38419461f, -0.39624670f, -0.40823088f, -0.42014512f, -0.43198737f,
+-0.44375560f, -0.45544780f, -0.46706195f, -0.47859608f, -0.49004821f,
+-0.50141636f, -0.51269860f, -0.52389299f, -0.53499762f, -0.54601058f,
+-0.55692998f, -0.56775395f, -0.57848064f, -0.58910822f, -0.59963485f,
+-0.61005873f, -0.62037809f, -0.63059115f, -0.64069616f, -0.65069139f,
+-0.66057513f, -0.67034568f, -0.68000137f, -0.68954054f, -0.69896157f,
+-0.70826283f, -0.71744274f, -0.72649972f, -0.73543221f, -0.74423869f,
+-0.75291765f, -0.76146760f, -0.76988708f, -0.77817464f, -0.78632887f,
+-0.79434836f, -0.80223175f, -0.80997767f, -0.81758481f, -0.82505187f,
+-0.83237755f, -0.83956061f, -0.84659981f, -0.85349396f, -0.86024186f,
+-0.86684237f, -0.87329434f, -0.87959669f, -0.88574831f, -0.89174817f,
+-0.89759523f, -0.90328850f, -0.90882699f, -0.91420976f, -0.91943588f,
+-0.92450446f, -0.92941463f, -0.93416555f, -0.93875641f, -0.94318642f,
+-0.94745482f, -0.95156087f, -0.95550388f, -0.95928317f, -0.96289809f,
+-0.96634802f, -0.96963238f, -0.97275059f, -0.97570213f, -0.97848649f,
+-0.98110318f, -0.98355177f, -0.98583184f, -0.98794298f, -0.98988485f,
+-0.99165711f, -0.99325945f, -0.99469160f, -0.99595331f, -0.99704438f,
+-0.99796460f, -0.99871383f, -0.99929194f, -0.99969882f, -0.99993441f,
+};
+#endif
+
+static const CELTMode mode96000_1920_240 = {
+96000,    /* Fs */
+240,    /* overlap */
+21,    /* nbEBands */
+21,    /* effEBands */
+{0.92300415f, 0.22000122f, 1.5128347f, 0.66101074f, },    /* preemph */
+eband5ms,    /* eBands */
+3,    /* maxLM */
+8,    /* nbShortMdcts */
+240,    /* shortMdctSize */
+11,    /* nbAllocVectors */
+band_allocation,    /* allocVectors */
+logN400,    /* logN */
+window240,    /* window */
+{3840, 3, {&fft_state96000_1920_0, &fft_state96000_1920_1, &fft_state96000_1920_2, &fft_state96000_1920_3, }, mdct_twiddles1920},    /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50},    /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50},    /* qext_cache */
+#endif
+};
+#endif /* ENABLE_QEXT */
+
+/* List of all the available modes */
+#ifdef ENABLE_QEXT
+#define TOTAL_MODES 2
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+&mode96000_1920_240,
+};
+#else
+#define TOTAL_MODES 1
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+};
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float_arm_ne10.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/static_modes_float_arm_ne10.h
new file mode 100644 (file)
index 0000000..66e1abb
--- /dev/null
@@ -0,0 +1,404 @@
+/* The contents of this file was automatically generated by
+ * dump_mode_arm_ne10.c with arguments: 48000 960
+ * It contains static definitions for some pre-defined modes. */
+#include <NE10_types.h>
+
+#ifndef NE10_FFT_PARAMS48000_960
+#define NE10_FFT_PARAMS48000_960
+static const ne10_int32_t ne10_factors_480[64] = {
+4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_240[64] = {
+3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_120[64] = {
+3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_int32_t ne10_factors_60[64] = {
+2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 ne10_fft_cpx_float32_t ne10_twiddles_480[480] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f},
+{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f},
+{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f},
+{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f},
+{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f},
+{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f},
+{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f},
+{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f},
+{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f},
+{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f},
+{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f},
+{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f},
+{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f},
+{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f},
+{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f},
+{1.0000000f,-0.0000000f}, {0.99991435f,-0.013089596f}, {0.99965733f,-0.026176950f},
+{0.99922901f,-0.039259817f}, {0.99862951f,-0.052335959f}, {0.99785894f,-0.065403134f},
+{0.99691731f,-0.078459099f}, {0.99580491f,-0.091501623f}, {0.99452192f,-0.10452846f},
+{0.99306846f,-0.11753740f}, {0.99144489f,-0.13052620f}, {0.98965138f,-0.14349262f},
+{0.98768836f,-0.15643448f}, {0.98555607f,-0.16934951f}, {0.98325491f,-0.18223552f},
+{0.98078525f,-0.19509032f}, {0.97814763f,-0.20791170f}, {0.97534233f,-0.22069745f},
+{0.97236991f,-0.23344538f}, {0.96923089f,-0.24615330f}, {0.96592581f,-0.25881904f},
+{0.96245521f,-0.27144045f}, {0.95881975f,-0.28401536f}, {0.95501995f,-0.29654160f},
+{0.95105648f,-0.30901700f}, {0.94693011f,-0.32143945f}, {0.94264150f,-0.33380687f},
+{0.93819129f,-0.34611708f}, {0.93358040f,-0.35836795f}, {0.92880952f,-0.37055743f},
+{0.92387956f,-0.38268346f}, {0.91879117f,-0.39474389f}, {0.91354543f,-0.40673664f},
+{0.90814316f,-0.41865975f}, {0.90258527f,-0.43051112f}, {0.89687270f,-0.44228873f},
+{0.89100653f,-0.45399052f}, {0.88498765f,-0.46561453f}, {0.87881708f,-0.47715878f},
+{0.87249601f,-0.48862126f}, {0.86602545f,-0.50000000f}, {0.85940641f,-0.51129311f},
+{0.85264015f,-0.52249855f}, {0.84572786f,-0.53361452f}, {0.83867055f,-0.54463905f},
+{0.83146960f,-0.55557024f}, {0.82412618f,-0.56640625f}, {0.81664151f,-0.57714522f},
+{0.80901700f,-0.58778524f}, {0.80125380f,-0.59832460f}, {0.79335332f,-0.60876143f},
+{0.78531694f,-0.61909395f}, {0.77714598f,-0.62932038f}, {0.76884180f,-0.63943899f},
+{0.76040596f,-0.64944810f}, {0.75183982f,-0.65934587f}, {0.74314475f,-0.66913062f},
+{0.73432249f,-0.67880076f}, {0.72537434f,-0.68835455f}, {0.71630192f,-0.69779050f},
+{0.70710677f,-0.70710683f}, {0.69779044f,-0.71630198f}, {0.68835455f,-0.72537440f},
+{0.67880070f,-0.73432255f}, {0.66913056f,-0.74314487f}, {0.65934581f,-0.75183982f},
+{0.64944804f,-0.76040596f}, {0.63943899f,-0.76884186f}, {0.62932038f,-0.77714598f},
+{0.61909395f,-0.78531694f}, {0.60876137f,-0.79335338f}, {0.59832460f,-0.80125386f},
+{0.58778524f,-0.80901700f}, {0.57714516f,-0.81664151f}, {0.56640625f,-0.82412618f},
+{0.55557019f,-0.83146960f}, {0.54463899f,-0.83867055f}, {0.53361452f,-0.84572786f},
+{0.52249849f,-0.85264015f}, {0.51129311f,-0.85940641f}, {0.49999997f,-0.86602545f},
+{0.48862118f,-0.87249601f}, {0.47715876f,-0.87881708f}, {0.46561447f,-0.88498765f},
+{0.45399052f,-0.89100653f}, {0.44228867f,-0.89687276f}, {0.43051103f,-0.90258533f},
+{0.41865975f,-0.90814316f}, {0.40673661f,-0.91354549f}, {0.39474380f,-0.91879129f},
+{0.38268343f,-0.92387956f}, {0.37055740f,-0.92880958f}, {0.35836786f,-0.93358046f},
+{0.34611705f,-0.93819135f}, {0.33380681f,-0.94264150f}, {0.32143947f,-0.94693011f},
+{0.30901697f,-0.95105654f}, {0.29654151f,-0.95501995f}, {0.28401533f,-0.95881975f},
+{0.27144039f,-0.96245527f}, {0.25881907f,-0.96592581f}, {0.24615327f,-0.96923089f},
+{0.23344530f,-0.97236991f}, {0.22069745f,-0.97534233f}, {0.20791166f,-0.97814763f},
+{0.19509023f,-0.98078531f}, {0.18223552f,-0.98325491f}, {0.16934945f,-0.98555607f},
+{0.15643437f,-0.98768836f}, {0.14349259f,-0.98965138f}, {0.13052613f,-0.99144489f},
+{0.11753740f,-0.99306846f}, {0.10452842f,-0.99452192f}, {0.091501534f,-0.99580491f},
+{0.078459084f,-0.99691731f}, {0.065403074f,-0.99785894f}, {0.052335974f,-0.99862951f},
+{0.039259788f,-0.99922901f}, {0.026176875f,-0.99965733f}, {0.013089597f,-0.99991435f},
+{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f},
+{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f},
+{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f},
+{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f},
+{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f},
+{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f},
+{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f},
+{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f},
+{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f},
+{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f},
+{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f},
+{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f},
+{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f},
+{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f},
+{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f},
+{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f},
+{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f},
+{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f},
+{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f},
+{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f},
+{-4.3711388e-08f,-1.0000000f}, {-0.026176963f,-0.99965733f}, {-0.052336060f,-0.99862951f},
+{-0.078459173f,-0.99691731f}, {-0.10452851f,-0.99452192f}, {-0.13052621f,-0.99144489f},
+{-0.15643445f,-0.98768836f}, {-0.18223560f,-0.98325491f}, {-0.20791174f,-0.97814757f},
+{-0.23344538f,-0.97236991f}, {-0.25881916f,-0.96592581f}, {-0.28401542f,-0.95881969f},
+{-0.30901703f,-0.95105648f}, {-0.33380687f,-0.94264150f}, {-0.35836795f,-0.93358040f},
+{-0.38268352f,-0.92387950f}, {-0.40673670f,-0.91354543f}, {-0.43051112f,-0.90258527f},
+{-0.45399061f,-0.89100647f}, {-0.47715873f,-0.87881708f}, {-0.50000006f,-0.86602533f},
+{-0.52249867f,-0.85264009f}, {-0.54463905f,-0.83867055f}, {-0.56640631f,-0.82412612f},
+{-0.58778518f,-0.80901700f}, {-0.60876143f,-0.79335332f}, {-0.62932050f,-0.77714586f},
+{-0.64944804f,-0.76040596f}, {-0.66913068f,-0.74314475f}, {-0.68835467f,-0.72537428f},
+{-0.70710677f,-0.70710677f}, {-0.72537446f,-0.68835449f}, {-0.74314493f,-0.66913044f},
+{-0.76040596f,-0.64944804f}, {-0.77714604f,-0.62932026f}, {-0.79335332f,-0.60876143f},
+{-0.80901700f,-0.58778518f}, {-0.82412624f,-0.56640613f}, {-0.83867055f,-0.54463899f},
+{-0.85264021f,-0.52249849f}, {-0.86602539f,-0.50000006f}, {-0.87881714f,-0.47715873f},
+{-0.89100659f,-0.45399037f}, {-0.90258527f,-0.43051112f}, {-0.91354549f,-0.40673658f},
+{-0.92387956f,-0.38268328f}, {-0.93358040f,-0.35836792f}, {-0.94264150f,-0.33380675f},
+{-0.95105654f,-0.30901679f}, {-0.95881975f,-0.28401530f}, {-0.96592587f,-0.25881892f},
+{-0.97236991f,-0.23344538f}, {-0.97814763f,-0.20791161f}, {-0.98325491f,-0.18223536f},
+{-0.98768836f,-0.15643445f}, {-0.99144489f,-0.13052608f}, {-0.99452192f,-0.10452849f},
+{-0.99691737f,-0.078459039f}, {-0.99862957f,-0.052335810f}, {-0.99965733f,-0.026176952f},
+{1.0000000f,-0.0000000f}, {0.99922901f,-0.039259817f}, {0.99691731f,-0.078459099f},
+{0.99306846f,-0.11753740f}, {0.98768836f,-0.15643448f}, {0.98078525f,-0.19509032f},
+{0.97236991f,-0.23344538f}, {0.96245521f,-0.27144045f}, {0.95105648f,-0.30901700f},
+{0.93819129f,-0.34611708f}, {0.92387956f,-0.38268346f}, {0.90814316f,-0.41865975f},
+{0.89100653f,-0.45399052f}, {0.87249601f,-0.48862126f}, {0.85264015f,-0.52249855f},
+{0.83146960f,-0.55557024f}, {0.80901700f,-0.58778524f}, {0.78531694f,-0.61909395f},
+{0.76040596f,-0.64944810f}, {0.73432249f,-0.67880076f}, {0.70710677f,-0.70710683f},
+{0.67880070f,-0.73432255f}, {0.64944804f,-0.76040596f}, {0.61909395f,-0.78531694f},
+{0.58778524f,-0.80901700f}, {0.55557019f,-0.83146960f}, {0.52249849f,-0.85264015f},
+{0.48862118f,-0.87249601f}, {0.45399052f,-0.89100653f}, {0.41865975f,-0.90814316f},
+{0.38268343f,-0.92387956f}, {0.34611705f,-0.93819135f}, {0.30901697f,-0.95105654f},
+{0.27144039f,-0.96245527f}, {0.23344530f,-0.97236991f}, {0.19509023f,-0.98078531f},
+{0.15643437f,-0.98768836f}, {0.11753740f,-0.99306846f}, {0.078459084f,-0.99691731f},
+{0.039259788f,-0.99922901f}, {-4.3711388e-08f,-1.0000000f}, {-0.039259877f,-0.99922901f},
+{-0.078459173f,-0.99691731f}, {-0.11753749f,-0.99306846f}, {-0.15643445f,-0.98768836f},
+{-0.19509032f,-0.98078525f}, {-0.23344538f,-0.97236991f}, {-0.27144048f,-0.96245521f},
+{-0.30901703f,-0.95105648f}, {-0.34611711f,-0.93819129f}, {-0.38268352f,-0.92387950f},
+{-0.41865984f,-0.90814310f}, {-0.45399061f,-0.89100647f}, {-0.48862135f,-0.87249595f},
+{-0.52249867f,-0.85264009f}, {-0.55557036f,-0.83146954f}, {-0.58778518f,-0.80901700f},
+{-0.61909389f,-0.78531694f}, {-0.64944804f,-0.76040596f}, {-0.67880076f,-0.73432249f},
+{-0.70710677f,-0.70710677f}, {-0.73432249f,-0.67880070f}, {-0.76040596f,-0.64944804f},
+{-0.78531694f,-0.61909389f}, {-0.80901700f,-0.58778518f}, {-0.83146966f,-0.55557019f},
+{-0.85264021f,-0.52249849f}, {-0.87249607f,-0.48862115f}, {-0.89100659f,-0.45399037f},
+{-0.90814322f,-0.41865960f}, {-0.92387956f,-0.38268328f}, {-0.93819135f,-0.34611690f},
+{-0.95105654f,-0.30901679f}, {-0.96245521f,-0.27144048f}, {-0.97236991f,-0.23344538f},
+{-0.98078531f,-0.19509031f}, {-0.98768836f,-0.15643445f}, {-0.99306846f,-0.11753736f},
+{-0.99691737f,-0.078459039f}, {-0.99922901f,-0.039259743f}, {-1.0000000f,8.7422777e-08f},
+{-0.99922901f,0.039259918f}, {-0.99691731f,0.078459218f}, {-0.99306846f,0.11753753f},
+{-0.98768830f,0.15643461f}, {-0.98078525f,0.19509049f}, {-0.97236985f,0.23344554f},
+{-0.96245515f,0.27144065f}, {-0.95105654f,0.30901697f}, {-0.93819135f,0.34611705f},
+{-0.92387956f,0.38268346f}, {-0.90814316f,0.41865975f}, {-0.89100653f,0.45399055f},
+{-0.87249601f,0.48862129f}, {-0.85264015f,0.52249861f}, {-0.83146960f,0.55557030f},
+{-0.80901694f,0.58778536f}, {-0.78531688f,0.61909401f}, {-0.76040590f,0.64944816f},
+{-0.73432243f,0.67880082f}, {-0.70710665f,0.70710689f}, {-0.67880058f,0.73432261f},
+{-0.64944792f,0.76040608f}, {-0.61909378f,0.78531706f}, {-0.58778507f,0.80901712f},
+{-0.55557001f,0.83146977f}, {-0.52249837f,0.85264033f}, {-0.48862100f,0.87249613f},
+{-0.45399022f,0.89100665f}, {-0.41865945f,0.90814328f}, {-0.38268313f,0.92387968f},
+{-0.34611672f,0.93819147f}, {-0.30901709f,0.95105648f}, {-0.27144054f,0.96245521f},
+{-0.23344545f,0.97236991f}, {-0.19509038f,0.98078525f}, {-0.15643452f,0.98768830f},
+{-0.11753743f,0.99306846f}, {-0.078459114f,0.99691731f}, {-0.039259821f,0.99922901f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_240[240] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f},
+{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f},
+{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f},
+{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f},
+{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f},
+{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f},
+{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f},
+{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f},
+{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f},
+{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f},
+{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f},
+{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f},
+{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f},
+{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f},
+{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f},
+{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f},
+{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f},
+{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f},
+{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f},
+{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f},
+{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f},
+{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f},
+{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f},
+{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f},
+{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{-4.3711388e-08f,-1.0000000f}, {-0.052336060f,-0.99862951f}, {-0.10452851f,-0.99452192f},
+{-0.15643445f,-0.98768836f}, {-0.20791174f,-0.97814757f}, {-0.25881916f,-0.96592581f},
+{-0.30901703f,-0.95105648f}, {-0.35836795f,-0.93358040f}, {-0.40673670f,-0.91354543f},
+{-0.45399061f,-0.89100647f}, {-0.50000006f,-0.86602533f}, {-0.54463905f,-0.83867055f},
+{-0.58778518f,-0.80901700f}, {-0.62932050f,-0.77714586f}, {-0.66913068f,-0.74314475f},
+{-0.70710677f,-0.70710677f}, {-0.74314493f,-0.66913044f}, {-0.77714604f,-0.62932026f},
+{-0.80901700f,-0.58778518f}, {-0.83867055f,-0.54463899f}, {-0.86602539f,-0.50000006f},
+{-0.89100659f,-0.45399037f}, {-0.91354549f,-0.40673658f}, {-0.93358040f,-0.35836792f},
+{-0.95105654f,-0.30901679f}, {-0.96592587f,-0.25881892f}, {-0.97814763f,-0.20791161f},
+{-0.98768836f,-0.15643445f}, {-0.99452192f,-0.10452849f}, {-0.99862957f,-0.052335810f},
+{1.0000000f,-0.0000000f}, {0.99691731f,-0.078459099f}, {0.98768836f,-0.15643448f},
+{0.97236991f,-0.23344538f}, {0.95105648f,-0.30901700f}, {0.92387956f,-0.38268346f},
+{0.89100653f,-0.45399052f}, {0.85264015f,-0.52249855f}, {0.80901700f,-0.58778524f},
+{0.76040596f,-0.64944810f}, {0.70710677f,-0.70710683f}, {0.64944804f,-0.76040596f},
+{0.58778524f,-0.80901700f}, {0.52249849f,-0.85264015f}, {0.45399052f,-0.89100653f},
+{0.38268343f,-0.92387956f}, {0.30901697f,-0.95105654f}, {0.23344530f,-0.97236991f},
+{0.15643437f,-0.98768836f}, {0.078459084f,-0.99691731f}, {-4.3711388e-08f,-1.0000000f},
+{-0.078459173f,-0.99691731f}, {-0.15643445f,-0.98768836f}, {-0.23344538f,-0.97236991f},
+{-0.30901703f,-0.95105648f}, {-0.38268352f,-0.92387950f}, {-0.45399061f,-0.89100647f},
+{-0.52249867f,-0.85264009f}, {-0.58778518f,-0.80901700f}, {-0.64944804f,-0.76040596f},
+{-0.70710677f,-0.70710677f}, {-0.76040596f,-0.64944804f}, {-0.80901700f,-0.58778518f},
+{-0.85264021f,-0.52249849f}, {-0.89100659f,-0.45399037f}, {-0.92387956f,-0.38268328f},
+{-0.95105654f,-0.30901679f}, {-0.97236991f,-0.23344538f}, {-0.98768836f,-0.15643445f},
+{-0.99691737f,-0.078459039f}, {-1.0000000f,8.7422777e-08f}, {-0.99691731f,0.078459218f},
+{-0.98768830f,0.15643461f}, {-0.97236985f,0.23344554f}, {-0.95105654f,0.30901697f},
+{-0.92387956f,0.38268346f}, {-0.89100653f,0.45399055f}, {-0.85264015f,0.52249861f},
+{-0.80901694f,0.58778536f}, {-0.76040590f,0.64944816f}, {-0.70710665f,0.70710689f},
+{-0.64944792f,0.76040608f}, {-0.58778507f,0.80901712f}, {-0.52249837f,0.85264033f},
+{-0.45399022f,0.89100665f}, {-0.38268313f,0.92387968f}, {-0.30901709f,0.95105648f},
+{-0.23344545f,0.97236991f}, {-0.15643452f,0.98768830f}, {-0.078459114f,0.99691731f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_120[120] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f},
+{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f},
+{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f},
+{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f},
+{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f},
+{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f},
+{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f},
+{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f},
+{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f},
+{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f},
+{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f},
+{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f},
+{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f},
+{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f},
+{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_60[60] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f},
+{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f},
+{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f},
+{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f},
+{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f},
+};
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_480 = {
+120,
+(ne10_int32_t *)ne10_factors_480,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_480,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_480[120],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_480 = {
+1,
+(void *)&ne10_fft_state_float32_t_480,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_240 = {
+60,
+(ne10_int32_t *)ne10_factors_240,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_240,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_240[60],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_240 = {
+1,
+(void *)&ne10_fft_state_float32_t_240,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_120 = {
+30,
+(ne10_int32_t *)ne10_factors_120,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_120,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_120[30],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_120 = {
+1,
+(void *)&ne10_fft_state_float32_t_120,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_60 = {
+15,
+(ne10_int32_t *)ne10_factors_60,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_60,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_60[15],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_60 = {
+1,
+(void *)&ne10_fft_state_float32_t_60,
+};
+
+#endif  /* end NE10_FFT_PARAMS48000_960 */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.c
new file mode 100644 (file)
index 0000000..fbe652f
--- /dev/null
@@ -0,0 +1,867 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "cwrs.h"
+#include "vq.h"
+#include "arch.h"
+#include "os_support.h"
+#include "bands.h"
+#include "rate.h"
+#include "pitch.h"
+#include "SigProc_FIX.h"
+
+#if defined(FIXED_POINT)
+void norm_scaleup(celt_norm *X, int N, int shift) {
+   int i;
+   celt_assert(shift >= 0);
+   if (shift <= 0) return;
+   for (i=0;i<N;i++) X[i] = SHL32(X[i], shift);
+}
+
+void norm_scaledown(celt_norm *X, int N, int shift) {
+   int i;
+   celt_assert(shift >= 0);
+   if (shift <= 0) return;
+   for (i=0;i<N;i++) X[i] = PSHR32(X[i], shift);
+}
+
+opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch) {
+   int i;
+   opus_val32 sum = 0;
+   (void)arch;
+   for (i=0;i<len;i++) sum += x[i]*y[i];
+   return sum;
+}
+opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch) {
+   int i;
+   opus_val64 sum = 0;
+   (void)arch;
+   for (i=0;i<len;i++) sum += x[i]*(opus_val64)y[i];
+   return sum>>2*(NORM_SHIFT-14);
+}
+#endif
+
+#ifndef OVERRIDE_vq_exp_rotation1
+static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
+{
+   int i;
+   opus_val16 ms;
+   celt_norm *Xptr;
+   Xptr = X;
+   ms = NEG16(s);
+   norm_scaledown(X, len, NORM_SHIFT-14);
+   for (i=0;i<len-stride;i++)
+   {
+      celt_norm x1, x2;
+      x1 = Xptr[0];
+      x2 = Xptr[stride];
+      Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2),  s, x1), 15));
+      *Xptr++      = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
+   }
+   Xptr = &X[len-2*stride-1];
+   for (i=len-2*stride-1;i>=0;i--)
+   {
+      celt_norm x1, x2;
+      x1 = Xptr[0];
+      x2 = Xptr[stride];
+      Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2),  s, x1), 15));
+      *Xptr--      = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
+   }
+   norm_scaleup(X, len, NORM_SHIFT-14);
+}
+#endif /* OVERRIDE_vq_exp_rotation1 */
+
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
+{
+   static const int SPREAD_FACTOR[3]={15,10,5};
+   int i;
+   opus_val16 c, s;
+   opus_val16 gain, theta;
+   int stride2=0;
+   int factor;
+
+   if (2*K>=len || spread==SPREAD_NONE)
+      return;
+   factor = SPREAD_FACTOR[spread-1];
+
+   gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
+   theta = HALF16(MULT16_16_Q15(gain,gain));
+
+   c = celt_cos_norm(EXTEND32(theta));
+   s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /*  sin(theta) */
+
+   if (len>=8*stride)
+   {
+      stride2 = 1;
+      /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
+         It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
+      while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
+         stride2++;
+   }
+   /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
+      extract_collapse_mask().*/
+   len = celt_udiv(len, stride);
+   for (i=0;i<stride;i++)
+   {
+      if (dir < 0)
+      {
+         if (stride2)
+            exp_rotation1(X+i*len, len, stride2, s, c);
+         exp_rotation1(X+i*len, len, 1, c, s);
+      } else {
+         exp_rotation1(X+i*len, len, 1, c, -s);
+         if (stride2)
+            exp_rotation1(X+i*len, len, stride2, s, -c);
+      }
+   }
+}
+
+/** Normalizes the decoded integer pvq codeword to unit norm. */
+static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
+      int N, opus_val32 Ryy, opus_val32 gain, int shift)
+{
+   int i;
+#ifdef FIXED_POINT
+   int k;
+#endif
+   opus_val32 t;
+   opus_val32 g;
+
+#ifdef FIXED_POINT
+   k = celt_ilog2(Ryy)>>1;
+#endif
+   t = VSHR32(Ryy, 2*(k-7)-15);
+   g = MULT32_32_Q31(celt_rsqrt_norm32(t),gain);
+   i=0;
+   (void)shift;
+#if defined(FIXED_POINT) && defined(ENABLE_QEXT)
+   if (shift>0) {
+      int tot_shift = NORM_SHIFT+1-k-shift;
+      if (tot_shift >= 0) {
+         do X[i] = MULT32_32_Q31(g, SHL32(iy[i], tot_shift));
+         while (++i < N);
+      } else {
+         do X[i] = MULT32_32_Q31(g, PSHR32(iy[i], -tot_shift));
+         while (++i < N);
+      }
+   } else
+#endif
+   do X[i] = VSHR32(MULT16_32_Q15(iy[i], g), k+15-NORM_SHIFT);
+   while (++i < N);
+}
+
+static unsigned extract_collapse_mask(int *iy, int N, int B)
+{
+   unsigned collapse_mask;
+   int N0;
+   int i;
+   if (B<=1)
+      return 1;
+   /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
+      exp_rotation().*/
+   N0 = celt_udiv(N, B);
+   collapse_mask = 0;
+   i=0; do {
+      int j;
+      unsigned tmp=0;
+      j=0; do {
+         tmp |= iy[i*N0+j];
+      } while (++j<N0);
+      collapse_mask |= (tmp!=0)<<i;
+   } while (++i<B);
+   return collapse_mask;
+}
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
+{
+   VARDECL(celt_norm, y);
+   VARDECL(int, signx);
+   int i, j;
+   int pulsesLeft;
+   opus_val32 sum;
+   opus_val32 xy;
+   opus_val16 yy;
+   SAVE_STACK;
+
+   (void)arch;
+   ALLOC(y, N, celt_norm);
+   ALLOC(signx, N, int);
+#ifdef FIXED_POINT
+   {
+      int shift = (celt_ilog2(1+celt_inner_prod_norm_shift(X, X, N, arch))+1)/2;
+      shift = IMAX(0, shift+(NORM_SHIFT-14)-14);
+      norm_scaledown(X, N, shift);
+   }
+#endif
+   /* Get rid of the sign */
+   sum = 0;
+   j=0; do {
+      signx[j] = X[j]<0;
+      /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
+      X[j] = ABS16(X[j]);
+      iy[j] = 0;
+      y[j] = 0;
+   } while (++j<N);
+
+   xy = yy = 0;
+
+   pulsesLeft = K;
+
+   /* Do a pre-search by projecting on the pyramid */
+   if (K > (N>>1))
+   {
+      opus_val16 rcp;
+      j=0; do {
+         sum += X[j];
+      }  while (++j<N);
+
+      /* If X is too small, just replace it with a pulse at 0 */
+#ifdef FIXED_POINT
+      if (sum <= K)
+#else
+      /* Prevents infinities and NaNs from causing too many pulses
+         to be allocated. 64 is an approximation of infinity here. */
+      if (!(sum > EPSILON && sum < 64))
+#endif
+      {
+         X[0] = QCONST16(1.f,14);
+         j=1; do
+            X[j]=0;
+         while (++j<N);
+         sum = QCONST16(1.f,14);
+      }
+#ifdef FIXED_POINT
+      rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
+#else
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
+#endif
+      j=0; do {
+#ifdef FIXED_POINT
+         /* It's really important to round *towards zero* here */
+         iy[j] = MULT16_16_Q15(X[j],rcp);
+#else
+         iy[j] = (int)floor(rcp*X[j]);
+#endif
+         y[j] = (celt_norm)iy[j];
+         yy = MAC16_16(yy, y[j],y[j]);
+         xy = MAC16_16(xy, X[j],y[j]);
+         y[j] *= 2;
+         pulsesLeft -= iy[j];
+      }  while (++j<N);
+   }
+   celt_sig_assert(pulsesLeft>=0);
+
+   /* This should never happen, but just in case it does (e.g. on silence)
+      we fill the first bin with pulses. */
+#ifdef FIXED_POINT_DEBUG
+   celt_sig_assert(pulsesLeft<=N+3);
+#endif
+   if (pulsesLeft > N+3)
+   {
+      opus_val16 tmp = (opus_val16)pulsesLeft;
+      yy = MAC16_16(yy, tmp, tmp);
+      yy = MAC16_16(yy, tmp, y[0]);
+      iy[0] += pulsesLeft;
+      pulsesLeft=0;
+   }
+
+   for (i=0;i<pulsesLeft;i++)
+   {
+      opus_val16 Rxy, Ryy;
+      int best_id;
+      opus_val32 best_num;
+      opus_val16 best_den;
+#ifdef FIXED_POINT
+      int rshift;
+#endif
+#ifdef FIXED_POINT
+      rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
+#endif
+      best_id = 0;
+      /* The squared magnitude term gets added anyway, so we might as well
+         add it outside the loop */
+      yy = ADD16(yy, 1);
+
+      /* Calculations for position 0 are out of the loop, in part to reduce
+         mispredicted branches (since the if condition is usually false)
+         in the loop. */
+      /* Temporary sums of the new pulse(s) */
+      Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      Ryy = ADD16(yy, y[0]);
+
+      /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+         Rxy is positive because the sign is pre-computed) */
+      Rxy = MULT16_16_Q15(Rxy,Rxy);
+      best_den = Ryy;
+      best_num = Rxy;
+      j=1;
+      do {
+         /* Temporary sums of the new pulse(s) */
+         Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
+         /* We're multiplying y[j] by two so we don't have to do it here */
+         Ryy = ADD16(yy, y[j]);
+
+         /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+            Rxy is positive because the sign is pre-computed) */
+         Rxy = MULT16_16_Q15(Rxy,Rxy);
+         /* The idea is to check for num/den >= best_num/best_den, but that way
+            we can do it without any division */
+         /* OPT: It's not clear whether a cmov is faster than a branch here
+            since the condition is more often false than true and using
+            a cmov introduces data dependencies across iterations. The optimal
+            choice may be architecture-dependent. */
+         if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
+         {
+            best_den = Ryy;
+            best_num = Rxy;
+            best_id = j;
+         }
+      } while (++j<N);
+
+      /* Updating the sums of the new pulse(s) */
+      xy = ADD32(xy, EXTEND32(X[best_id]));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      yy = ADD16(yy, y[best_id]);
+
+      /* Only now that we've made the final choice, update y/iy */
+      /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+      y[best_id] += 2;
+      iy[best_id]++;
+   }
+
+   /* Put the original sign back */
+   j=0;
+   do {
+      /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
+      /* OPT: The is more likely to be compiled without a branch than the code above
+         but has the same performance otherwise. */
+      iy[j] = (iy[j]^-signx[j]) + signx[j];
+   } while (++j<N);
+   RESTORE_STACK;
+   return yy;
+}
+
+#ifdef ENABLE_QEXT
+#include "macros.h"
+
+static opus_val32 op_pvq_search_N2(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int shift) {
+   opus_val32 sum;
+   opus_val32 rcp_sum;
+   int offset;
+   sum = ABS32(X[0]) + ABS32(X[1]);
+   if (sum < EPSILON) {
+      iy[0] = K;
+      up_iy[0] = up*K;
+      iy[1]=up_iy[1]=0;
+      *refine=0;
+#ifdef FIXED_POINT
+      return (opus_val64)K*K*up*up>>2*shift;
+#else
+      (void)shift;
+      return K*(float)K*up*up;
+#endif
+   }
+#ifdef FIXED_POINT
+   int sum_shift;
+   opus_val32 X0;
+   sum_shift = 30-celt_ilog2(sum);
+   rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift));
+   X0 = MULT32_32_Q31(SHL32(X[0], sum_shift), rcp_sum);
+   iy[0] = PSHR32(MULT32_32_Q31(SHL32(K, 8), X0), 7);
+   up_iy[0] = PSHR32(MULT32_32_Q31(SHL32(up*K, 8), X0), 7);
+#else
+   rcp_sum = 1.f/sum;
+   iy[0] = (int)floor(.5f+K*X[0]*rcp_sum);
+   up_iy[0] = (int)floor(.5f+up*K*X[0]*rcp_sum);
+#endif
+   up_iy[0] = IMAX(up*iy[0] - (up-1)/2, IMIN(up*iy[0] + (up-1)/2, up_iy[0]));
+   offset = up_iy[0] - up*iy[0];
+   iy[1] = K-abs(iy[0]);
+   up_iy[1] = up*K-abs(up_iy[0]);
+   if (X[1] < 0) {
+      iy[1] = -iy[1];
+      up_iy[1] = -up_iy[1];
+      offset = -offset;
+   }
+   *refine = offset;
+#ifdef FIXED_POINT
+   return (up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1] + (1<<2*shift>>1))>>2*shift;
+#else
+   return up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1];
+#endif
+}
+
+static int op_pvq_refine(const opus_val32 *Xn, int *iy, int *iy0, int K, int up, int margin, int N) {
+   int i;
+   int dir;
+   VARDECL(opus_val32, rounding);
+   int iysum = 0;
+   SAVE_STACK;
+   ALLOC(rounding, N, opus_val32);
+   for (i=0;i<N;i++) {
+      opus_val32 tmp;
+      tmp = MULT32_32_Q31(SHL32(K, 8), Xn[i]);
+#ifdef FIXED_POINT
+      iy[i] = (tmp+64) >> 7;
+#else
+      iy[i] = (int)floor(.5+tmp);
+#endif
+      rounding[i] = tmp - SHL32(iy[i], 7);
+   }
+   if (iy != iy0) {
+      for (i=0;i<N;i++) iy[i] = IMIN(up*iy0[i]+up-1, IMAX(up*iy0[i]-up+1, iy[i]));
+   }
+   for (i=0;i<N;i++) iysum += iy[i];
+   if (abs(iysum - K) > 32) {
+      RESTORE_STACK;
+      return 1;
+   }
+   dir = iysum < K ? 1 : -1;
+   while (iysum != K) {
+      opus_val32 roundval=-1000000*dir;
+      int roundpos=0;
+      for (i=0;i<N;i++) {
+         if ((rounding[i]-roundval)*dir > 0 && abs(iy[i]-up*iy0[i]) < (margin-1) && !(dir==-1 && iy[i] == 0)) {
+            roundval = rounding[i];
+            roundpos = i;
+         }
+      }
+      iy[roundpos] += dir;
+      rounding[roundpos] -= SHL32(dir, 15);
+      iysum+=dir;
+   }
+   RESTORE_STACK;
+   return 0;
+}
+
+static opus_val32 op_pvq_search_extra(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int N, int shift) {
+   opus_val32 rcp_sum;
+   opus_val32 sum=0;
+   int i;
+   int failed=0;
+   opus_val64 yy=0;
+   VARDECL(opus_val32, Xn);
+   SAVE_STACK;
+   for (i=0;i<N;i++) sum += ABS32(X[i]);
+   ALLOC(Xn, N, opus_val32);
+   if (sum < EPSILON)
+      failed = 1;
+   else {
+#ifdef FIXED_POINT
+      int sum_shift = 30-celt_ilog2(sum);
+      rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift));
+      for (i=0;i<N;i++) {
+         Xn[i] = MULT32_32_Q31(SHL32(ABS32(X[i]), sum_shift), rcp_sum);
+      }
+#else
+      rcp_sum = celt_rcp(sum);
+      for (i=0;i<N;i++) {
+         Xn[i] = ABS32(X[i])*rcp_sum;
+      }
+#endif
+   }
+   failed = failed || op_pvq_refine(Xn, iy, iy, K, 1, K+1, N);
+   failed = failed || op_pvq_refine(Xn, up_iy, iy, up*K, up, up, N);
+   if (failed) {
+      iy[0] = K;
+      for (i=1;i<N;i++) iy[i] = 0;
+      up_iy[0] = up*K;
+      for (i=1;i<N;i++) up_iy[i] = 0;
+   }
+   for (i=0;i<N;i++) {
+      yy += up_iy[i]*(opus_val64)up_iy[i];
+      if (X[i] < 0) {
+         iy[i] = -iy[i];
+         up_iy[i] = -up_iy[i];
+      }
+      refine[i] = up_iy[i]-up*iy[i];
+   }
+   RESTORE_STACK;
+#ifdef FIXED_POINT
+   return (yy + (1<<2*shift>>1))>>2*shift;
+#else
+   (void)shift;
+   return yy;
+#endif
+}
+#endif
+
+#ifdef ENABLE_QEXT
+/* Take advantage of the fact that "large" refine values are much less likely
+   than smaller ones. */
+static void ec_enc_refine(ec_enc *enc, opus_int32 refine, opus_int32 up, int extra_bits, int use_entropy) {
+   int large;
+   large = abs(refine)>up/2;
+   ec_enc_bit_logp(enc, large, use_entropy ? 3 : 1);
+   if (large) {
+      ec_enc_bits(enc, refine < 0, 1);
+      ec_enc_bits(enc, abs(refine)-up/2-1, extra_bits-1);
+   } else {
+      ec_enc_bits(enc, refine+up/2, extra_bits);
+   }
+}
+
+static int ec_dec_refine(ec_enc *dec, opus_int32 up, int extra_bits, int use_entropy) {
+   int large, refine;
+   large = ec_dec_bit_logp(dec, use_entropy ? 3 : 1);
+   if (large) {
+      int sign = ec_dec_bits(dec, 1);
+      refine = ec_dec_bits(dec, extra_bits-1) + up/2+1;
+      if (sign) refine = -refine;
+   } else {
+      refine = (opus_int32)ec_dec_bits(dec, extra_bits)-up/2;
+   }
+   return refine;
+}
+#endif
+
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val32 gain, int resynth
+      ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch)
+{
+   VARDECL(int, iy);
+   opus_val32 yy;
+   unsigned collapse_mask;
+#ifdef ENABLE_QEXT
+   int yy_shift = 0;
+#endif
+   SAVE_STACK;
+
+   celt_assert2(K>0, "alg_quant() needs at least one pulse");
+   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
+
+   /* Covers vectorization by up to 4. */
+   ALLOC(iy, N+3, int);
+
+   exp_rotation(X, N, 1, B, K, spread);
+
+#ifdef ENABLE_QEXT
+   if (N==2 && extra_bits >= 2) {
+      int refine;
+      int up_iy[2];
+      int up;
+      yy_shift = IMAX(0, extra_bits-7);
+      up = (1<<extra_bits)-1;
+      yy = op_pvq_search_N2(X, iy, up_iy, K, up, &refine, yy_shift);
+      collapse_mask = extract_collapse_mask(up_iy, N, B);
+      encode_pulses(iy, N, K, enc);
+      ec_enc_uint(ext_enc, refine+(up-1)/2, up);
+      if (resynth)
+         normalise_residual(up_iy, X, N, yy, gain, yy_shift);
+   } else if (extra_bits >= 2) {
+      int i;
+      VARDECL(int, up_iy);
+      VARDECL(int, refine);
+      int up, use_entropy;
+      ALLOC(up_iy, N, int);
+      ALLOC(refine, N, int);
+      yy_shift = IMAX(0, extra_bits-7);
+      up = (1<<extra_bits)-1;
+      yy = op_pvq_search_extra(X, iy, up_iy, K, up, refine, N, yy_shift);
+      collapse_mask = extract_collapse_mask(up_iy, N, B);
+      encode_pulses(iy, N, K, enc);
+      use_entropy = (ext_enc->storage*8 - ec_tell(ext_enc)) > (unsigned)(N-1)*(extra_bits+3)+1;
+      for (i=0;i<N-1;i++) ec_enc_refine(ext_enc, refine[i], up, extra_bits, use_entropy);
+      if (iy[N-1]==0) ec_enc_bits(ext_enc, up_iy[N-1]<0, 1);
+      if (resynth)
+         normalise_residual(up_iy, X, N, yy, gain, yy_shift);
+   } else
+#endif
+   {
+      yy = op_pvq_search(X, iy, K, N, arch);
+      collapse_mask = extract_collapse_mask(iy, N, B);
+      encode_pulses(iy, N, K, enc);
+      if (resynth)
+         normalise_residual(iy, X, N, yy, gain, 0);
+   }
+
+   if (resynth)
+      exp_rotation(X, N, -1, B, K, spread);
+
+   RESTORE_STACK;
+   return collapse_mask;
+}
+
+/** Decode pulse vector and combine the result with the pitch vector to produce
+    the final normalised signal in the current band. */
+unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
+      ec_dec *dec, opus_val32 gain
+      ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits))
+{
+   opus_val32 Ryy;
+   unsigned collapse_mask;
+   VARDECL(int, iy);
+   int yy_shift=0;
+   SAVE_STACK;
+
+   celt_assert2(K>0, "alg_unquant() needs at least one pulse");
+   celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
+   ALLOC(iy, N, int);
+   Ryy = decode_pulses(iy, N, K, dec);
+#ifdef ENABLE_QEXT
+   if (N==2 && extra_bits >= 2) {
+      int up;
+      int refine;
+      yy_shift = IMAX(0, extra_bits-7);
+      up = (1<<extra_bits)-1;
+      refine = (opus_int32)ec_dec_uint(ext_dec, up) - (up-1)/2;
+      iy[0] *= up;
+      iy[1] *= up;
+      if (iy[1] == 0) {
+         iy[1] = (iy[0] > 0) ? -refine : refine;
+         iy[0] += (refine*(opus_int64)iy[0] > 0) ? -refine : refine;
+      } else if (iy[1] > 0) {
+         iy[0] += refine;
+         iy[1] -= refine*(iy[0]>0?1:-1);
+      } else {
+         iy[0] -= refine;
+         iy[1] -= refine*(iy[0]>0?1:-1);
+      }
+#ifdef FIXED_POINT
+      Ryy = (iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1] + (1<<2*yy_shift>>1)) >> 2*yy_shift;
+#else
+      Ryy = iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1];
+#endif
+   } else if (extra_bits >= 2) {
+      int i;
+      opus_val64 yy64;
+      VARDECL(int, refine);
+      int up, use_entropy;
+      int sign=0;
+      ALLOC(refine, N, int);
+      yy_shift = IMAX(0, extra_bits-7);
+      up = (1<<extra_bits)-1;
+      use_entropy = (ext_dec->storage*8 - ec_tell(ext_dec)) > (unsigned)(N-1)*(extra_bits+3)+1;
+      for (i=0;i<N-1;i++) refine[i] = ec_dec_refine(ext_dec, up, extra_bits, use_entropy);
+      if (iy[N-1]==0) sign = ec_dec_bits(ext_dec, 1);
+      else sign = iy[N-1] < 0;
+      for (i=0;i<N-1;i++) {
+         iy[i] = iy[i]*up + refine[i];
+      }
+      iy[N-1] = up*K;
+      for (i=0;i<N-1;i++) iy[N-1] -= abs(iy[i]);
+      if (sign) iy[N-1] = -iy[N-1];
+      yy64 = 0;
+      for (i=0;i<N;i++) yy64 += iy[i]*(opus_val64)iy[i];
+#ifdef FIXED_POINT
+      Ryy = (yy64 + (1<<2*yy_shift>>1)) >> 2*yy_shift;
+#else
+      Ryy = yy64;
+#endif
+   }
+#endif
+   normalise_residual(iy, X, N, Ryy, gain, yy_shift);
+   exp_rotation(X, N, -1, B, K, spread);
+   collapse_mask = extract_collapse_mask(iy, N, B);
+   RESTORE_STACK;
+   return collapse_mask;
+}
+
+#ifndef OVERRIDE_renormalise_vector
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch)
+{
+   int i;
+#ifdef FIXED_POINT
+   int k;
+#endif
+   opus_val32 E;
+   opus_val16 g;
+   opus_val32 t;
+   celt_norm *xptr;
+   norm_scaledown(X, N, NORM_SHIFT-14);
+   E = EPSILON + celt_inner_prod_norm(X, X, N, arch);
+#ifdef FIXED_POINT
+   k = celt_ilog2(E)>>1;
+#endif
+   t = VSHR32(E, 2*(k-7));
+   g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
+
+   xptr = X;
+   for (i=0;i<N;i++)
+   {
+      *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+15-14));
+      xptr++;
+   }
+   norm_scaleup(X, N, NORM_SHIFT-14);
+   /*return celt_sqrt(E);*/
+}
+#endif /* OVERRIDE_renormalise_vector */
+
+opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch)
+{
+   int i;
+   int itheta;
+   opus_val32 mid, side;
+   opus_val32 Emid, Eside;
+
+   Emid = Eside = 0;
+   if (stereo)
+   {
+      for (i=0;i<N;i++)
+      {
+         celt_norm m, s;
+         m = PSHR32(ADD32(X[i], Y[i]), NORM_SHIFT-13);
+         s = PSHR32(SUB32(X[i], Y[i]), NORM_SHIFT-13);
+         Emid = MAC16_16(Emid, m, m);
+         Eside = MAC16_16(Eside, s, s);
+      }
+   } else {
+      Emid += celt_inner_prod_norm_shift(X, X, N, arch);
+      Eside += celt_inner_prod_norm_shift(Y, Y, N, arch);
+   }
+   mid = celt_sqrt32(Emid);
+   side = celt_sqrt32(Eside);
+#if defined(FIXED_POINT)
+   itheta = celt_atan2p_norm(side, mid);
+#else
+   itheta = (int)floor(.5f+65536.f*16384*celt_atan2p_norm(side,mid));
+#endif
+
+   return itheta;
+}
+
+#ifdef ENABLE_QEXT
+
+static void cubic_synthesis(celt_norm *X, int *iy, int N, int K, int face, int sign, opus_val32 gain) {
+   int i;
+   opus_val32 sum=0;
+   opus_val32 mag;
+#ifdef FIXED_POINT
+   int sum_shift;
+   int shift = IMAX(celt_ilog2(K) + celt_ilog2(N)/2 - 13, 0);
+#endif
+   for (i=0;i<N;i++) {
+      X[i] = (1+2*iy[i])-K;
+   }
+   X[face] = sign ? -K : K;
+   for (i=0;i<N;i++) {
+      sum += PSHR32(MULT16_16(X[i],X[i]), 2*shift);
+   }
+#ifdef FIXED_POINT
+   sum_shift = (29-celt_ilog2(sum))>>1;
+   mag = celt_rsqrt_norm32(SHL32(sum, 2*sum_shift+1));
+   for (i=0;i<N;i++) {
+      X[i] = VSHR32(MULT16_32_Q15(X[i],MULT32_32_Q31(mag,gain)), shift-sum_shift+29-NORM_SHIFT);
+   }
+#else
+   mag = 1.f/sqrt(sum);
+   for (i=0;i<N;i++) {
+      X[i] *= mag*gain;
+   }
+#endif
+}
+
+unsigned cubic_quant(celt_norm *X, int N, int res, int B, ec_enc *enc, opus_val32 gain, int resynth) {
+   int i;
+   int face=0;
+   int K;
+   VARDECL(int, iy);
+   celt_norm faceval=-1;
+   opus_val32 norm;
+   int sign;
+   SAVE_STACK;
+   ALLOC(iy, N, int);
+   K = 1<<res;
+   /* Using odd K on transients to avoid adding pre-echo. */
+   if (B!=1) K=IMAX(1, K-1);
+   if (K==1) {
+      if (resynth) OPUS_CLEAR(X, N);
+      RESTORE_STACK;
+      return 0;
+   }
+   for (i=0;i<N;i++) {
+      if (ABS32(X[i]) > faceval) {
+         faceval = ABS32(X[i]);
+         face = i;
+      }
+   }
+   sign = X[face]<0;
+   ec_enc_uint(enc, face, N);
+   ec_enc_bits(enc, sign, 1);
+#ifdef FIXED_POINT
+   if (faceval != 0) {
+      int face_shift = 30-celt_ilog2(faceval);
+      norm = celt_rcp_norm32(SHL32(faceval, face_shift));
+      norm = MULT16_32_Q15(K, norm);
+      for (i=0;i<N;i++) {
+         /* By computing X[i]+faceval inside the shift, the result is guaranteed non-negative. */
+         iy[i] = IMIN(K-1, (MULT32_32_Q31(SHL32(X[i]+faceval, face_shift-1), norm)) >> 15);
+      }
+   } else {
+      OPUS_CLEAR(iy, N);
+   }
+#else
+   norm = .5f*K/(faceval+EPSILON);
+   for (i=0;i<N;i++) {
+      iy[i] = IMIN(K-1, (int)floor((X[i]+faceval)*norm));
+   }
+#endif
+   for (i=0;i<N;i++) {
+      if (i != face) ec_enc_bits(enc, iy[i], res);
+   }
+   if (resynth) {
+      cubic_synthesis(X, iy, N, K, face, sign, gain);
+   }
+   RESTORE_STACK;
+   return (1<<B)-1;
+}
+
+unsigned cubic_unquant(celt_norm *X, int N, int res, int B, ec_dec *dec, opus_val32 gain) {
+   int i;
+   int face;
+   int sign;
+   int K;
+   VARDECL(int, iy);
+   SAVE_STACK;
+   ALLOC(iy, N, int);
+   K = 1<<res;
+   /* Using odd K on transients to avoid adding pre-echo. */
+   if (B!=1) K=IMAX(1, K-1);
+   if (K==1) {
+      OPUS_CLEAR(X, N);
+      RESTORE_STACK;
+      return 0;
+   }
+   face = ec_dec_uint(dec, N);
+   sign = ec_dec_bits(dec, 1);
+   for (i=0;i<N;i++) {
+      if (i != face) iy[i] = ec_dec_bits(dec, res);
+   }
+   iy[face]=0;
+   cubic_synthesis(X, iy, N, K, face, sign, gain);
+   RESTORE_STACK;
+   return (1<<B)-1;
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/vq.h
new file mode 100644 (file)
index 0000000..07fa44a
--- /dev/null
@@ -0,0 +1,98 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/**
+   @file vq.h
+   @brief Vector quantisation of the residual
+ */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef VQ_H
+#define VQ_H
+
+#include "entenc.h"
+#include "entdec.h"
+#include "modes.h"
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
+#include "x86/vq_sse.h"
+#endif
+
+#if defined(FIXED_POINT)
+opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch);
+opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch);
+
+void norm_scaleup(celt_norm *X, int N, int shift);
+void norm_scaledown(celt_norm *X, int N, int shift);
+
+#else
+#define celt_inner_prod_norm celt_inner_prod
+#define celt_inner_prod_norm_shift celt_inner_prod
+#define norm_scaleup(X, N, shift)
+#define norm_scaledown(X, N, shift)
+#endif
+
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
+
+#if !defined(OVERRIDE_OP_PVQ_SEARCH)
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_c(x, iy, K, N, arch))
+#endif
+
+/** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
+  * the pitch and a combination of pulses such that its norm is still equal
+  * to 1. This is the function that will typically require the most CPU.
+ * @param X Residual signal to quantise/encode (returns quantised version)
+ * @param N Number of samples to encode
+ * @param K Number of pulses to use
+ * @param enc Entropy encoder state
+ * @ret A mask indicating which blocks in the band received pulses
+*/
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val32 gain, int resynth
+      ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch);
+
+/** Algebraic pulse decoder
+ * @param X Decoded normalised spectrum (returned)
+ * @param N Number of samples to decode
+ * @param K Number of pulses to use
+ * @param dec Entropy decoder state
+ * @ret A mask indicating which blocks in the band received pulses
+ */
+unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
+      ec_dec *dec, opus_val32 gain
+      ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits));
+
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch);
+
+opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);
+
+unsigned cubic_quant(celt_norm *X, int N, int K, int B, ec_enc *enc, opus_val32 gain, int resynth);
+unsigned cubic_unquant(celt_norm *X, int N, int K, int B, ec_dec *dec, opus_val32 gain);
+
+#endif /* VQ_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse.h
new file mode 100644 (file)
index 0000000..90e69ec
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CELT_LPC_SSE_H
+#define CELT_LPC_SSE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+
+void celt_fir_sse4_1(
+         const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16 *y,
+         int N,
+         int ord,
+         int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE4_1)
+#define OVERRIDE_CELT_FIR
+#define celt_fir(x, num, y, N, ord, arch) \
+    ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
+
+#elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16 *y,
+         int N,
+         int ord,
+         int arch);
+
+#define OVERRIDE_CELT_FIR
+#  define celt_fir(x, num, y, N, ord, arch) \
+    ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
+
+#endif
+#endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse4_1.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/celt_lpc_sse4_1.c
new file mode 100644 (file)
index 0000000..229a762
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+#include "x86cpu.h"
+
+#if defined(FIXED_POINT)
+
+void celt_fir_sse4_1(const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16 *y,
+         int N,
+         int ord,
+         int arch)
+{
+    int i,j;
+    VARDECL(opus_val16, rnum);
+
+    __m128i vecNoA;
+    opus_int32 noA ;
+    SAVE_STACK;
+
+   ALLOC(rnum, ord, opus_val16);
+   for(i=0;i<ord;i++)
+      rnum[i] = num[ord-i-1];
+   noA = EXTEND32(1) << SIG_SHIFT >> 1;
+   vecNoA = _mm_set_epi32(noA, noA, noA, noA);
+
+   for (i=0;i<N-3;i+=4)
+   {
+      opus_val32 sums[4] = {0};
+      __m128i vecSum, vecX;
+#if defined(OPUS_CHECK_ASM)
+      {
+         opus_val32 sums_c[4] = {0};
+         xcorr_kernel_c(rnum, x+i-ord, sums_c, ord);
+#endif
+         xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
+#if defined(OPUS_CHECK_ASM)
+         celt_assert(memcmp(sums, sums_c, sizeof(sums)) == 0);
+      }
+#endif
+      vecSum = _mm_loadu_si128((__m128i *)(void*)sums);
+      vecSum = _mm_add_epi32(vecSum, vecNoA);
+      vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT);
+      vecX = OP_CVTEPI16_EPI32_M64(x + i);
+      vecSum = _mm_add_epi32(vecSum, vecX);
+      vecSum = _mm_packs_epi32(vecSum, vecSum);
+      _mm_storel_epi64((__m128i *)(void *)(y + i), vecSum);
+   }
+   for (;i<N;i++)
+   {
+      opus_val32 sum = 0;
+      for (j=0;j<ord;j++)
+         sum = MAC16_16(sum, rnum[j], x[i+j-ord]);
+      y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT)));
+   }
+
+   RESTORE_STACK;
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_avx.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_avx.c
new file mode 100644 (file)
index 0000000..f731762
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (c) 2023 Amazon */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <immintrin.h>
+#include "x86cpu.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(FIXED_POINT)
+
+/* Like the "regular" xcorr_kernel(), but computes 8 results at a time. */
+static void xcorr_kernel_avx(const float *x, const float *y, float sum[8], int len)
+{
+    __m256 xsum0, xsum1, xsum2, xsum3, xsum4, xsum5, xsum6, xsum7;
+    xsum7 = xsum6 = xsum5 = xsum4 = xsum3 = xsum2 = xsum1 = xsum0 = _mm256_setzero_ps();
+    int i;
+    __m256 x0;
+    /* Compute 8 inner products using partial sums. */
+    for (i=0;i<len-7;i+=8)
+    {
+        x0 = _mm256_loadu_ps(x+i);
+        xsum0 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i  ), xsum0);
+        xsum1 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+1), xsum1);
+        xsum2 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+2), xsum2);
+        xsum3 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+3), xsum3);
+        xsum4 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+4), xsum4);
+        xsum5 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+5), xsum5);
+        xsum6 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+6), xsum6);
+        xsum7 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+7), xsum7);
+    }
+    if (i != len) {
+        static const int mask[15] = {-1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0};
+        __m256i m;
+        m = _mm256_loadu_si256((__m256i*)(void*)(mask + 7+i-len));
+        x0 = _mm256_maskload_ps(x+i, m);
+        xsum0 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i  , m), xsum0);
+        xsum1 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+1, m), xsum1);
+        xsum2 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+2, m), xsum2);
+        xsum3 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+3, m), xsum3);
+        xsum4 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+4, m), xsum4);
+        xsum5 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+5, m), xsum5);
+        xsum6 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+6, m), xsum6);
+        xsum7 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+7, m), xsum7);
+    }
+    /* 8 horizontal adds. */
+    /* Compute [0 4] [1 5] [2 6] [3 7] */
+    xsum0 = _mm256_add_ps(_mm256_permute2f128_ps(xsum0, xsum4, 2<<4), _mm256_permute2f128_ps(xsum0, xsum4, 1 | (3<<4)));
+    xsum1 = _mm256_add_ps(_mm256_permute2f128_ps(xsum1, xsum5, 2<<4), _mm256_permute2f128_ps(xsum1, xsum5, 1 | (3<<4)));
+    xsum2 = _mm256_add_ps(_mm256_permute2f128_ps(xsum2, xsum6, 2<<4), _mm256_permute2f128_ps(xsum2, xsum6, 1 | (3<<4)));
+    xsum3 = _mm256_add_ps(_mm256_permute2f128_ps(xsum3, xsum7, 2<<4), _mm256_permute2f128_ps(xsum3, xsum7, 1 | (3<<4)));
+    /* Compute [0 1 4 5] [2 3 6 7] */
+    xsum0 = _mm256_hadd_ps(xsum0, xsum1);
+    xsum1 = _mm256_hadd_ps(xsum2, xsum3);
+    /* Compute [0 1 2 3 4 5 6 7] */
+    xsum0 = _mm256_hadd_ps(xsum0, xsum1);
+    _mm256_storeu_ps(sum, xsum0);
+}
+
+void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch)
+{
+   int i;
+   celt_assert(max_pitch>0);
+   (void)arch;
+   for (i=0;i<max_pitch-7;i+=8)
+   {
+      xcorr_kernel_avx(_x, _y+i, &xcorr[i], len);
+   }
+   for (;i<max_pitch;i++)
+   {
+      xcorr[i] = celt_inner_prod(_x, _y+i, len, arch);
+   }
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.c
new file mode 100644 (file)
index 0000000..20e7312
--- /dev/null
@@ -0,0 +1,185 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+
+#include <xmmintrin.h>
+#include "arch.h"
+
+void xcorr_kernel_sse(const opus_val16 *x, const opus_val16 *y, opus_val32 sum[4], int len)
+{
+   int j;
+   __m128 xsum1, xsum2;
+   xsum1 = _mm_loadu_ps(sum);
+   xsum2 = _mm_setzero_ps();
+
+   for (j = 0; j < len-3; j += 4)
+   {
+      __m128 x0 = _mm_loadu_ps(x+j);
+      __m128 yj = _mm_loadu_ps(y+j);
+      __m128 y3 = _mm_loadu_ps(y+j+3);
+
+      xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x00),yj));
+      xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x55),
+                                          _mm_shuffle_ps(yj,y3,0x49)));
+      xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xaa),
+                                          _mm_shuffle_ps(yj,y3,0x9e)));
+      xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xff),y3));
+   }
+   if (j < len)
+   {
+      xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+      if (++j < len)
+      {
+         xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+         if (++j < len)
+         {
+            xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+         }
+      }
+   }
+   _mm_storeu_ps(sum,_mm_add_ps(xsum1,xsum2));
+}
+
+
+void dual_inner_prod_sse(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+   int i;
+   __m128 xsum1, xsum2;
+   xsum1 = _mm_setzero_ps();
+   xsum2 = _mm_setzero_ps();
+   for (i=0;i<N-3;i+=4)
+   {
+      __m128 xi = _mm_loadu_ps(x+i);
+      __m128 y1i = _mm_loadu_ps(y01+i);
+      __m128 y2i = _mm_loadu_ps(y02+i);
+      xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(xi, y1i));
+      xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(xi, y2i));
+   }
+   /* Horizontal sum */
+   xsum1 = _mm_add_ps(xsum1, _mm_movehl_ps(xsum1, xsum1));
+   xsum1 = _mm_add_ss(xsum1, _mm_shuffle_ps(xsum1, xsum1, 0x55));
+   _mm_store_ss(xy1, xsum1);
+   xsum2 = _mm_add_ps(xsum2, _mm_movehl_ps(xsum2, xsum2));
+   xsum2 = _mm_add_ss(xsum2, _mm_shuffle_ps(xsum2, xsum2, 0x55));
+   _mm_store_ss(xy2, xsum2);
+   for (;i<N;i++)
+   {
+      *xy1 = MAC16_16(*xy1, x[i], y01[i]);
+      *xy2 = MAC16_16(*xy2, x[i], y02[i]);
+   }
+}
+
+opus_val32 celt_inner_prod_sse(const opus_val16 *x, const opus_val16 *y,
+      int N)
+{
+   int i;
+   float xy;
+   __m128 sum;
+   sum = _mm_setzero_ps();
+   /* FIXME: We should probably go 8-way and use 2 sums. */
+   for (i=0;i<N-3;i+=4)
+   {
+      __m128 xi = _mm_loadu_ps(x+i);
+      __m128 yi = _mm_loadu_ps(y+i);
+      sum = _mm_add_ps(sum,_mm_mul_ps(xi, yi));
+   }
+   /* Horizontal sum */
+   sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
+   sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
+   _mm_store_ss(&xy, sum);
+   for (;i<N;i++)
+   {
+      xy = MAC16_16(xy, x[i], y[i]);
+   }
+   return xy;
+}
+
+void comb_filter_const_sse(opus_val32 *y, opus_val32 *x, int T, int N,
+      opus_val16 g10, opus_val16 g11, opus_val16 g12)
+{
+   int i;
+   __m128 x0v;
+   __m128 g10v, g11v, g12v;
+   g10v = _mm_load1_ps(&g10);
+   g11v = _mm_load1_ps(&g11);
+   g12v = _mm_load1_ps(&g12);
+   x0v = _mm_loadu_ps(&x[-T-2]);
+   for (i=0;i<N-3;i+=4)
+   {
+      __m128 yi, yi2, x1v, x2v, x3v, x4v;
+      const opus_val32 *xp = &x[i-T-2];
+      yi = _mm_loadu_ps(x+i);
+      x4v = _mm_loadu_ps(xp+4);
+#if 0
+      /* Slower version with all loads */
+      x1v = _mm_loadu_ps(xp+1);
+      x2v = _mm_loadu_ps(xp+2);
+      x3v = _mm_loadu_ps(xp+3);
+#else
+      x2v = _mm_shuffle_ps(x0v, x4v, 0x4e);
+      x1v = _mm_shuffle_ps(x0v, x2v, 0x99);
+      x3v = _mm_shuffle_ps(x2v, x4v, 0x99);
+#endif
+
+      yi = _mm_add_ps(yi, _mm_mul_ps(g10v,x2v));
+#if 0 /* Set to 1 to make it bit-exact with the non-SSE version */
+      yi = _mm_add_ps(yi, _mm_mul_ps(g11v,_mm_add_ps(x3v,x1v)));
+      yi = _mm_add_ps(yi, _mm_mul_ps(g12v,_mm_add_ps(x4v,x0v)));
+#else
+      /* Use partial sums */
+      yi2 = _mm_add_ps(_mm_mul_ps(g11v,_mm_add_ps(x3v,x1v)),
+                       _mm_mul_ps(g12v,_mm_add_ps(x4v,x0v)));
+      yi = _mm_add_ps(yi, yi2);
+#endif
+      x0v=x4v;
+      _mm_storeu_ps(y+i, yi);
+   }
+#ifdef CUSTOM_MODES
+   for (;i<N;i++)
+   {
+      y[i] = x[i]
+               + MULT16_32_Q15(g10,x[i-T])
+               + MULT16_32_Q15(g11,ADD32(x[i-T+1],x[i-T-1]))
+               + MULT16_32_Q15(g12,ADD32(x[i-T+2],x[i-T-2]));
+   }
+#endif
+}
+
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse.h
new file mode 100644 (file)
index 0000000..127581f
--- /dev/null
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013 Jean-Marc Valin and John Ridges
+   Copyright (c) 2014, Cisco Systems, INC MingXiang WeiZhou MinPeng YanWang*/
+/**
+   @file pitch_sse.h
+   @brief Pitch analysis
+ */
+
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PITCH_SSE_H
+#define PITCH_SSE_H
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+void xcorr_kernel_sse4_1(
+                    const opus_int16 *x,
+                    const opus_int16 *y,
+                    opus_val32       sum[4],
+                    int              len);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+void xcorr_kernel_sse(
+                    const opus_val16 *x,
+                    const opus_val16 *y,
+                    opus_val32       sum[4],
+                    int              len);
+#endif
+
+#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT)
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+    ((void)arch, xcorr_kernel_sse4_1(x, y, sum, len))
+
+#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT)
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+    ((void)arch, xcorr_kernel_sse(x, y, sum, len))
+
+#elif defined(OPUS_HAVE_RTCD) &&  ((defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)) || (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)))
+
+extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+                    const opus_val16 *x,
+                    const opus_val16 *y,
+                    opus_val32       sum[4],
+                    int              len);
+
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+    ((*XCORR_KERNEL_IMPL[(arch) & OPUS_ARCHMASK])(x, y, sum, len))
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse4_1(
+    const opus_int16 *x,
+    const opus_int16 *y,
+    int               N);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse2(
+    const opus_int16 *x,
+    const opus_int16 *y,
+    int               N);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse(
+    const opus_val16 *x,
+    const opus_val16 *y,
+    int               N);
+#endif
+
+
+#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+    ((void)arch, celt_inner_prod_sse4_1(x, y, N))
+
+#elif defined(OPUS_X86_PRESUME_SSE2) && defined(FIXED_POINT) && !defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+    ((void)arch, celt_inner_prod_sse2(x, y, N))
+
+#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+    ((void)arch, celt_inner_prod_sse(x, y, N))
+
+
+#elif defined(OPUS_HAVE_RTCD) && (((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT)) || \
+    (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)))
+
+extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+                    const opus_val16 *x,
+                    const opus_val16 *y,
+                    int               N);
+
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+    ((*CELT_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y, N))
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+
+void dual_inner_prod_sse(const opus_val16 *x,
+    const opus_val16 *y01,
+    const opus_val16 *y02,
+    int               N,
+    opus_val32       *xy1,
+    opus_val32       *xy2);
+
+void comb_filter_const_sse(opus_val32 *y,
+    opus_val32 *x,
+    int         T,
+    int         N,
+    opus_val16  g10,
+    opus_val16  g11,
+    opus_val16  g12);
+
+
+#if defined(OPUS_X86_PRESUME_SSE)
+#define OVERRIDE_DUAL_INNER_PROD
+#define OVERRIDE_COMB_FILTER_CONST
+# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+    ((void)(arch),dual_inner_prod_sse(x, y01, y02, N, xy1, xy2))
+
+# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+    ((void)(arch),comb_filter_const_sse(y, x, T, N, g10, g11, g12))
+#elif defined(OPUS_HAVE_RTCD)
+
+#define OVERRIDE_DUAL_INNER_PROD
+#define OVERRIDE_COMB_FILTER_CONST
+extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+              const opus_val16 *x,
+              const opus_val16 *y01,
+              const opus_val16 *y02,
+              int               N,
+              opus_val32       *xy1,
+              opus_val32       *xy2);
+
+#define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+    ((*DUAL_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
+
+extern void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
+              opus_val32 *y,
+              opus_val32 *x,
+              int         T,
+              int         N,
+              opus_val16  g10,
+              opus_val16  g11,
+              opus_val16  g12);
+
+#define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+    ((*COMB_FILTER_CONST_IMPL[(arch) & OPUS_ARCHMASK])(y, x, T, N, g10, g11, g12))
+
+#define NON_STATIC_COMB_FILTER_CONST_C
+
+#endif
+
+void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch);
+
+#if defined(OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_avx2
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_PITCH_XCORR
+extern void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])(
+              const float *_x,
+              const float *_y,
+              float *xcorr,
+              int len,
+              int max_pitch,
+              int arch
+              );
+
+#define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+    ((*PITCH_XCORR_IMPL[(arch) & OPUS_ARCHMASK])(_x, _y, xcorr, len, max_pitch, arch))
+
+
+#endif /* OPUS_X86_PRESUME_AVX2 && !OPUS_HAVE_RTCD */
+
+#endif /* OPUS_X86_MAY_HAVE_SSE && !FIXED_POINT */
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse2.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse2.c
new file mode 100644 (file)
index 0000000..114f211
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse2(const opus_val16 *x, const opus_val16 *y,
+      int N)
+{
+    opus_int  i, dataSize16;
+    opus_int32 sum;
+
+    __m128i inVec1_76543210, inVec1_FEDCBA98, acc1;
+    __m128i inVec2_76543210, inVec2_FEDCBA98, acc2;
+
+    sum = 0;
+    dataSize16 = N & ~15;
+
+    acc1 = _mm_setzero_si128();
+    acc2 = _mm_setzero_si128();
+
+    for (i=0;i<dataSize16;i+=16)
+    {
+        inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+        inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+        inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8]));
+        inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8]));
+
+        inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+        inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98);
+
+        acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+        acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98);
+    }
+
+    acc1 = _mm_add_epi32( acc1, acc2 );
+
+    if (N - i >= 8)
+    {
+        inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+        inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+        inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+
+        acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+        i += 8;
+    }
+
+    acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64( acc1, acc1));
+    acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16( acc1, 0x0E));
+    sum += _mm_cvtsi128_si32(acc1);
+
+    for (;i<N;i++) {
+        sum = silk_SMLABB(sum, x[i], y[i]);
+    }
+
+    return sum;
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse4_1.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/pitch_sse4_1.c
new file mode 100644 (file)
index 0000000..a14ea41
--- /dev/null
@@ -0,0 +1,240 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+#include <smmintrin.h>
+#include "x86cpu.h"
+
+opus_val32 celt_inner_prod_sse4_1(const opus_val16 *x, const opus_val16 *y,
+      int N)
+{
+    opus_int  i, dataSize16;
+    opus_int32 sum;
+    __m128i inVec1_76543210, inVec1_FEDCBA98, acc1;
+    __m128i inVec2_76543210, inVec2_FEDCBA98, acc2;
+    __m128i inVec1_3210, inVec2_3210;
+
+    sum = 0;
+    dataSize16 = N & ~15;
+
+    acc1 = _mm_setzero_si128();
+    acc2 = _mm_setzero_si128();
+
+    for (i=0;i<dataSize16;i+=16) {
+        inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+        inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+        inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8]));
+        inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8]));
+
+        inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+        inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98);
+
+        acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+        acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98);
+    }
+
+    acc1 = _mm_add_epi32(acc1, acc2);
+
+    if (N - i >= 8)
+    {
+        inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+        inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+        inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+
+        acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+        i += 8;
+    }
+
+    if (N - i >= 4)
+    {
+        inVec1_3210 = OP_CVTEPI16_EPI32_M64(&x[i + 0]);
+        inVec2_3210 = OP_CVTEPI16_EPI32_M64(&y[i + 0]);
+
+        inVec1_3210 = _mm_mullo_epi32(inVec1_3210, inVec2_3210);
+
+        acc1 = _mm_add_epi32(acc1, inVec1_3210);
+        i += 4;
+    }
+
+    acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64(acc1, acc1));
+    acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16(acc1, 0x0E));
+
+    sum += _mm_cvtsi128_si32(acc1);
+
+    for (;i<N;i++)
+    {
+        sum = silk_SMLABB(sum, x[i], y[i]);
+    }
+
+    return sum;
+}
+
+void xcorr_kernel_sse4_1(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[ 4 ], int len)
+{
+    int j;
+
+    __m128i vecX, vecX0, vecX1, vecX2, vecX3;
+    __m128i vecY0, vecY1, vecY2, vecY3;
+    __m128i sum0, sum1, sum2, sum3, vecSum;
+    __m128i initSum;
+
+#ifdef OPUS_CHECK_ASM
+    opus_val32 sum_c[4];
+    for (j=0;j<4;j++) {
+      sum_c[j] = sum[j];
+    }
+    xcorr_kernel_c(x, y, sum_c, len);
+#endif
+
+    celt_assert(len >= 3);
+
+    sum0 = _mm_setzero_si128();
+    sum1 = _mm_setzero_si128();
+    sum2 = _mm_setzero_si128();
+    sum3 = _mm_setzero_si128();
+
+    for (j=0;j<(len-7);j+=8)
+    {
+        vecX = _mm_loadu_si128((__m128i *)(void*)(&x[j + 0]));
+        vecY0 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 0]));
+        vecY1 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 1]));
+        vecY2 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 2]));
+        vecY3 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 3]));
+
+        sum0 = _mm_add_epi32(sum0, _mm_madd_epi16(vecX, vecY0));
+        sum1 = _mm_add_epi32(sum1, _mm_madd_epi16(vecX, vecY1));
+        sum2 = _mm_add_epi32(sum2, _mm_madd_epi16(vecX, vecY2));
+        sum3 = _mm_add_epi32(sum3, _mm_madd_epi16(vecX, vecY3));
+    }
+
+    sum0 = _mm_add_epi32(sum0, _mm_unpackhi_epi64( sum0, sum0));
+    sum0 = _mm_add_epi32(sum0, _mm_shufflelo_epi16( sum0, 0x0E));
+
+    sum1 = _mm_add_epi32(sum1, _mm_unpackhi_epi64( sum1, sum1));
+    sum1 = _mm_add_epi32(sum1, _mm_shufflelo_epi16( sum1, 0x0E));
+
+    sum2 = _mm_add_epi32(sum2, _mm_unpackhi_epi64( sum2, sum2));
+    sum2 = _mm_add_epi32(sum2, _mm_shufflelo_epi16( sum2, 0x0E));
+
+    sum3 = _mm_add_epi32(sum3, _mm_unpackhi_epi64( sum3, sum3));
+    sum3 = _mm_add_epi32(sum3, _mm_shufflelo_epi16( sum3, 0x0E));
+
+    vecSum = _mm_unpacklo_epi64(_mm_unpacklo_epi32(sum0, sum1),
+          _mm_unpacklo_epi32(sum2, sum3));
+
+    for (;j<(len-3);j+=4)
+    {
+        vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]);
+        vecX0 = _mm_shuffle_epi32(vecX, 0x00);
+        vecX1 = _mm_shuffle_epi32(vecX, 0x55);
+        vecX2 = _mm_shuffle_epi32(vecX, 0xaa);
+        vecX3 = _mm_shuffle_epi32(vecX, 0xff);
+
+        vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+        vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+        vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]);
+        vecY3 = OP_CVTEPI16_EPI32_M64(&y[j + 3]);
+
+        sum0 = _mm_mullo_epi32(vecX0, vecY0);
+        sum1 = _mm_mullo_epi32(vecX1, vecY1);
+        sum2 = _mm_mullo_epi32(vecX2, vecY2);
+        sum3 = _mm_mullo_epi32(vecX3, vecY3);
+
+        sum0 = _mm_add_epi32(sum0, sum1);
+        sum2 = _mm_add_epi32(sum2, sum3);
+        vecSum = _mm_add_epi32(vecSum, sum0);
+        vecSum = _mm_add_epi32(vecSum, sum2);
+    }
+
+    vecX = OP_CVTEPI16_EPI32_M64(&x[len - 4]);
+    if (len - j == 3)
+    {
+        vecX0 = _mm_shuffle_epi32(vecX, 0x55);
+        vecX1 = _mm_shuffle_epi32(vecX, 0xaa);
+        vecX2 = _mm_shuffle_epi32(vecX, 0xff);
+
+        vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+        vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+        vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]);
+
+        sum0 = _mm_mullo_epi32(vecX0, vecY0);
+        sum1 = _mm_mullo_epi32(vecX1, vecY1);
+        sum2 = _mm_mullo_epi32(vecX2, vecY2);
+
+        vecSum = _mm_add_epi32(vecSum, sum0);
+        vecSum = _mm_add_epi32(vecSum, sum1);
+        vecSum = _mm_add_epi32(vecSum, sum2);
+    }
+    else if (len - j == 2)
+    {
+        vecX0 = _mm_shuffle_epi32(vecX, 0xaa);
+        vecX1 = _mm_shuffle_epi32(vecX, 0xff);
+
+        vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+        vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+
+        sum0 = _mm_mullo_epi32(vecX0, vecY0);
+        sum1 = _mm_mullo_epi32(vecX1, vecY1);
+
+        vecSum = _mm_add_epi32(vecSum, sum0);
+        vecSum = _mm_add_epi32(vecSum, sum1);
+    }
+    else if (len - j == 1)
+    {
+        vecX0 = _mm_shuffle_epi32(vecX, 0xff);
+
+        vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+
+        sum0 = _mm_mullo_epi32(vecX0, vecY0);
+
+        vecSum = _mm_add_epi32(vecSum, sum0);
+    }
+
+    initSum = _mm_loadu_si128((__m128i *)(void*)(&sum[0]));
+    initSum = _mm_add_epi32(initSum, vecSum);
+    _mm_storeu_si128((__m128i *)(void*)sum, initSum);
+
+#ifdef OPUS_CHECK_ASM
+    celt_assert(!memcmp(sum_c, sum, sizeof(sum_c)));
+#endif
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse.h
new file mode 100644 (file)
index 0000000..444503b
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright (c) 2016  Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef VQ_SSE_H
+#define VQ_SSE_H
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE2)
+
+#define OVERRIDE_OP_PVQ_SEARCH
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_sse2(x, iy, K, N, arch))
+
+#elif defined(OPUS_HAVE_RTCD)
+
+#define OVERRIDE_OP_PVQ_SEARCH
+extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch);
+
+#  define op_pvq_search(X, iy, K, N, arch) \
+    ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch))
+
+#endif
+#endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse2.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/vq_sse2.c
new file mode 100644 (file)
index 0000000..4c4ebf8
--- /dev/null
@@ -0,0 +1,217 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2007-2016 Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "vq.h"
+#include "x86cpu.h"
+
+
+#ifndef FIXED_POINT
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch)
+{
+   int i, j;
+   int pulsesLeft;
+   float xy, yy;
+   VARDECL(celt_norm, y);
+   VARDECL(celt_norm, X);
+   VARDECL(float, signy);
+   __m128 signmask;
+   __m128 sums;
+   __m128i fours;
+   SAVE_STACK;
+
+   (void)arch;
+   /* All bits set to zero, except for the sign bit. */
+   signmask = _mm_set_ps1(-0.f);
+   fours = _mm_set_epi32(4, 4, 4, 4);
+   ALLOC(y, N+3, celt_norm);
+   ALLOC(X, N+3, celt_norm);
+   ALLOC(signy, N+3, float);
+
+   OPUS_COPY(X, _X, N);
+   X[N] = X[N+1] = X[N+2] = 0;
+   sums = _mm_setzero_ps();
+   for (j=0;j<N;j+=4)
+   {
+      __m128 x4, s4;
+      x4 = _mm_loadu_ps(&X[j]);
+      s4 = _mm_cmplt_ps(x4, _mm_setzero_ps());
+      /* Get rid of the sign */
+      x4 = _mm_andnot_ps(signmask, x4);
+      sums = _mm_add_ps(sums, x4);
+      /* Clear y and iy in case we don't do the projection. */
+      _mm_storeu_ps(&y[j], _mm_setzero_ps());
+      _mm_storeu_si128((__m128i*)(void*)&iy[j], _mm_setzero_si128());
+      _mm_storeu_ps(&X[j], x4);
+      _mm_storeu_ps(&signy[j], s4);
+   }
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)));
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1)));
+
+   xy = yy = 0;
+
+   pulsesLeft = K;
+
+   /* Do a pre-search by projecting on the pyramid */
+   if (K > (N>>1))
+   {
+      __m128i pulses_sum;
+      __m128 yy4, xy4;
+      __m128 rcp4;
+      opus_val32 sum = _mm_cvtss_f32(sums);
+      /* If X is too small, just replace it with a pulse at 0 */
+      /* Prevents infinities and NaNs from causing too many pulses
+         to be allocated. 64 is an approximation of infinity here. */
+      if (!(sum > EPSILON && sum < 64))
+      {
+         X[0] = QCONST16(1.f,14);
+         j=1; do
+            X[j]=0;
+         while (++j<N);
+         sums = _mm_set_ps1(1.f);
+      }
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums));
+      xy4 = yy4 = _mm_setzero_ps();
+      pulses_sum = _mm_setzero_si128();
+      for (j=0;j<N;j+=4)
+      {
+         __m128 rx4, x4, y4;
+         __m128i iy4;
+         x4 = _mm_loadu_ps(&X[j]);
+         rx4 = _mm_mul_ps(x4, rcp4);
+         iy4 = _mm_cvttps_epi32(rx4);
+         pulses_sum = _mm_add_epi32(pulses_sum, iy4);
+         _mm_storeu_si128((__m128i*)(void*)&iy[j], iy4);
+         y4 = _mm_cvtepi32_ps(iy4);
+         xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4));
+         yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4));
+         /* double the y[] vector so we don't have to do it in the search loop. */
+         _mm_storeu_ps(&y[j], _mm_add_ps(y4, y4));
+      }
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2)));
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1)));
+      pulsesLeft -= _mm_cvtsi128_si32(pulses_sum);
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      xy = _mm_cvtss_f32(xy4);
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      yy = _mm_cvtss_f32(yy4);
+   }
+   X[N] = X[N+1] = X[N+2] = -100;
+   y[N] = y[N+1] = y[N+2] = 100;
+   celt_sig_assert(pulsesLeft>=0);
+
+   /* This should never happen, but just in case it does (e.g. on silence)
+      we fill the first bin with pulses. */
+   if (pulsesLeft > N+3)
+   {
+      opus_val16 tmp = (opus_val16)pulsesLeft;
+      yy = MAC16_16(yy, tmp, tmp);
+      yy = MAC16_16(yy, tmp, y[0]);
+      iy[0] += pulsesLeft;
+      pulsesLeft=0;
+   }
+
+   for (i=0;i<pulsesLeft;i++)
+   {
+      int best_id;
+      __m128 xy4, yy4;
+      __m128 max, max2;
+      __m128i count;
+      __m128i pos;
+      /* The squared magnitude term gets added anyway, so we might as well
+         add it outside the loop */
+      yy = ADD16(yy, 1);
+      xy4 = _mm_load1_ps(&xy);
+      yy4 = _mm_load1_ps(&yy);
+      max = _mm_setzero_ps();
+      pos = _mm_setzero_si128();
+      count = _mm_set_epi32(3, 2, 1, 0);
+      for (j=0;j<N;j+=4)
+      {
+         __m128 x4, y4, r4;
+         x4 = _mm_loadu_ps(&X[j]);
+         y4 = _mm_loadu_ps(&y[j]);
+         x4 = _mm_add_ps(x4, xy4);
+         y4 = _mm_add_ps(y4, yy4);
+         y4 = _mm_rsqrt_ps(y4);
+         r4 = _mm_mul_ps(x4, y4);
+         /* Update the index of the max. */
+         pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max))));
+         /* Update the max. */
+         max = _mm_max_ps(max, r4);
+         /* Update the indices (+4) */
+         count = _mm_add_epi32(count, fours);
+      }
+      /* Horizontal max */
+      max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2)));
+      max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1)));
+      /* Now that max2 contains the max at all positions, look at which value(s) of the
+         partial max is equal to the global max. */
+      pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2)));
+      pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos));
+      pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2)));
+      best_id = _mm_cvtsi128_si32(pos);
+
+      /* Updating the sums of the new pulse(s) */
+      xy = ADD32(xy, EXTEND32(X[best_id]));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      yy = ADD16(yy, y[best_id]);
+
+      /* Only now that we've made the final choice, update y/iy */
+      /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+      y[best_id] += 2;
+      iy[best_id]++;
+   }
+
+   /* Put the original sign back */
+   for (j=0;j<N;j+=4)
+   {
+      __m128i y4;
+      __m128i s4;
+      y4 = _mm_loadu_si128((__m128i*)(void*)&iy[j]);
+      s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j]));
+      y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4);
+      _mm_storeu_si128((__m128i*)(void*)&iy[j], y4);
+   }
+   RESTORE_STACK;
+   return yy;
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_arch_macros.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_arch_macros.h
new file mode 100644 (file)
index 0000000..975b443
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (c) 2023 Amazon */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef _MSC_VER
+
+# ifdef OPUS_X86_MAY_HAVE_SSE
+#  ifndef __SSE__
+#   define __SSE__
+#  endif
+# endif
+
+# ifdef OPUS_X86_MAY_HAVE_SSE2
+#  ifndef __SSE2__
+#   define __SSE2__
+#  endif
+# endif
+
+# ifdef OPUS_X86_MAY_HAVE_SSE4_1
+#  ifndef __SSE4_1__
+#   define __SSE4_1__
+#  endif
+# endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_celt_map.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86_celt_map.c
new file mode 100644 (file)
index 0000000..ba8eafe
--- /dev/null
@@ -0,0 +1,187 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include "x86/x86cpu.h"
+#include "celt_lpc.h"
+#include "pitch.h"
+#include "pitch_sse.h"
+#include "vq.h"
+
+#if defined(OPUS_HAVE_RTCD)
+
+# if defined(FIXED_POINT)
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)
+
+void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *num,
+         opus_val16       *y,
+         int              N,
+         int              ord,
+         int              arch
+) = {
+  celt_fir_c,                /* non-sse */
+  celt_fir_c,
+  celt_fir_c,
+  MAY_HAVE_SSE4_1(celt_fir), /* sse4.1  */
+  MAY_HAVE_SSE4_1(celt_fir)  /* avx  */
+};
+
+void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *y,
+         opus_val32       sum[4],
+         int              len
+) = {
+  xcorr_kernel_c,                /* non-sse */
+  xcorr_kernel_c,
+  xcorr_kernel_c,
+  MAY_HAVE_SSE4_1(xcorr_kernel), /* sse4.1  */
+  MAY_HAVE_SSE4_1(xcorr_kernel)  /* avx  */
+};
+
+#endif
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) ||  \
+ (!defined(OPUS_X86_MAY_HAVE_SSE_4_1) && defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2))
+
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *y,
+         int              N
+) = {
+  celt_inner_prod_c,                /* non-sse */
+  celt_inner_prod_c,
+  MAY_HAVE_SSE2(celt_inner_prod),
+  MAY_HAVE_SSE4_1(celt_inner_prod), /* sse4.1  */
+  MAY_HAVE_SSE4_1(celt_inner_prod)  /* avx  */
+};
+
+#endif
+
+# else
+
+#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)
+
+void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])(
+         const float *_x,
+         const float *_y,
+         float *xcorr,
+         int len,
+         int max_pitch,
+         int arch
+) = {
+  celt_pitch_xcorr_c,                /* non-sse */
+  celt_pitch_xcorr_c,
+  celt_pitch_xcorr_c,
+  celt_pitch_xcorr_c,
+  MAY_HAVE_AVX2(celt_pitch_xcorr)
+};
+
+#endif
+
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)
+
+void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *y,
+         opus_val32       sum[4],
+         int              len
+) = {
+  xcorr_kernel_c,                /* non-sse */
+  MAY_HAVE_SSE(xcorr_kernel),
+  MAY_HAVE_SSE(xcorr_kernel),
+  MAY_HAVE_SSE(xcorr_kernel),
+  MAY_HAVE_SSE(xcorr_kernel)
+};
+
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+         const opus_val16 *x,
+         const opus_val16 *y,
+         int              N
+) = {
+  celt_inner_prod_c,                /* non-sse */
+  MAY_HAVE_SSE(celt_inner_prod),
+  MAY_HAVE_SSE(celt_inner_prod),
+  MAY_HAVE_SSE(celt_inner_prod),
+  MAY_HAVE_SSE(celt_inner_prod)
+};
+
+void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+                    const opus_val16 *x,
+                    const opus_val16 *y01,
+                    const opus_val16 *y02,
+                    int               N,
+                    opus_val32       *xy1,
+                    opus_val32       *xy2
+) = {
+  dual_inner_prod_c,                /* non-sse */
+  MAY_HAVE_SSE(dual_inner_prod),
+  MAY_HAVE_SSE(dual_inner_prod),
+  MAY_HAVE_SSE(dual_inner_prod),
+  MAY_HAVE_SSE(dual_inner_prod)
+};
+
+void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
+              opus_val32 *y,
+              opus_val32 *x,
+              int         T,
+              int         N,
+              opus_val16  g10,
+              opus_val16  g11,
+              opus_val16  g12
+) = {
+  comb_filter_const_c,                /* non-sse */
+  MAY_HAVE_SSE(comb_filter_const),
+  MAY_HAVE_SSE(comb_filter_const),
+  MAY_HAVE_SSE(comb_filter_const),
+  MAY_HAVE_SSE(comb_filter_const)
+};
+
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)
+opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch
+) = {
+  op_pvq_search_c,                /* non-sse */
+  op_pvq_search_c,
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search)
+};
+#endif
+
+#endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.c b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.c
new file mode 100644 (file)
index 0000000..2e7c32a
--- /dev/null
@@ -0,0 +1,184 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cpu_support.h"
+#include "macros.h"
+#include "main.h"
+#include "pitch.h"
+#include "x86cpu.h"
+
+#if defined(OPUS_HAVE_RTCD) && \
+  ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+  (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+
+#if defined(_MSC_VER)
+
+#include <intrin.h>
+static _inline void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
+{
+    __cpuid((int*)CPUInfo, InfoType);
+}
+
+#else
+
+#if defined(CPU_INFO_BY_C)
+#include <cpuid.h>
+#endif
+
+static void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
+{
+#if defined(CPU_INFO_BY_ASM)
+#if defined(__i386__) && defined(__PIC__)
+/* %ebx is PIC register in 32-bit, so mustn't clobber it. */
+    __asm__ __volatile__ (
+        "xchg %%ebx, %1\n"
+        "cpuid\n"
+        "xchg %%ebx, %1\n":
+        "=a" (CPUInfo[0]),
+        "=r" (CPUInfo[1]),
+        "=c" (CPUInfo[2]),
+        "=d" (CPUInfo[3]) :
+        /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
+        "0" (InfoType), "2" (0)
+    );
+#else
+    __asm__ __volatile__ (
+        "cpuid":
+        "=a" (CPUInfo[0]),
+        "=b" (CPUInfo[1]),
+        "=c" (CPUInfo[2]),
+        "=d" (CPUInfo[3]) :
+        /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
+        "0" (InfoType), "2" (0)
+    );
+#endif
+#elif defined(CPU_INFO_BY_C)
+    /* We use __get_cpuid_count to clear ECX to avoid a valgrind false-positive
+        prior to v3.17.0.*/
+    if (!__get_cpuid_count(InfoType, 0, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]))) {
+        /* Our function cannot fail, but __get_cpuid{_count} can.
+           Returning all zeroes will effectively disable all SIMD, which is
+            what we want on CPUs that don't support CPUID. */
+        CPUInfo[3] = CPUInfo[2] = CPUInfo[1] = CPUInfo[0] = 0;
+    }
+#else
+# error "Configured to use x86 RTCD, but no CPU detection method available. " \
+ "Reconfigure with --disable-rtcd (or send patches)."
+#endif
+}
+
+#endif
+
+typedef struct CPU_Feature{
+    /*  SIMD: 128-bit */
+    int HW_SSE;
+    int HW_SSE2;
+    int HW_SSE41;
+    /*  SIMD: 256-bit */
+    int HW_AVX2;
+} CPU_Feature;
+
+static void opus_cpu_feature_check(CPU_Feature *cpu_feature)
+{
+    unsigned int info[4];
+    unsigned int nIds = 0;
+
+    cpuid(info, 0);
+    nIds = info[0];
+
+    if (nIds >= 1){
+        cpuid(info, 1);
+        cpu_feature->HW_SSE = (info[3] & (1 << 25)) != 0;
+        cpu_feature->HW_SSE2 = (info[3] & (1 << 26)) != 0;
+        cpu_feature->HW_SSE41 = (info[2] & (1 << 19)) != 0;
+        cpu_feature->HW_AVX2 = (info[2] & (1 << 28)) != 0 && (info[2] & (1 << 12)) != 0;
+        if (cpu_feature->HW_AVX2 && nIds >= 7) {
+            cpuid(info, 7);
+            cpu_feature->HW_AVX2 = cpu_feature->HW_AVX2 && (info[1] & (1 << 5)) != 0;
+        } else {
+            cpu_feature->HW_AVX2 = 0;
+        }
+    }
+    else {
+        cpu_feature->HW_SSE = 0;
+        cpu_feature->HW_SSE2 = 0;
+        cpu_feature->HW_SSE41 = 0;
+        cpu_feature->HW_AVX2 = 0;
+    }
+}
+
+static int opus_select_arch_impl(void)
+{
+    CPU_Feature cpu_feature;
+    int arch;
+
+    opus_cpu_feature_check(&cpu_feature);
+
+    arch = 0;
+    if (!cpu_feature.HW_SSE)
+    {
+       return arch;
+    }
+    arch++;
+
+    if (!cpu_feature.HW_SSE2)
+    {
+       return arch;
+    }
+    arch++;
+
+    if (!cpu_feature.HW_SSE41)
+    {
+        return arch;
+    }
+    arch++;
+
+    if (!cpu_feature.HW_AVX2)
+    {
+        return arch;
+    }
+    arch++;
+
+    return arch;
+}
+
+int opus_select_arch(void) {
+    int arch = opus_select_arch_impl();
+#ifdef FUZZING
+    /* Randomly downgrade the architecture. */
+    arch = rand()%(arch+1);
+#endif
+    return arch;
+}
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.h b/code/sdk/zhihui/test_opus_frame_to_pcm/celt/x86/x86cpu.h
new file mode 100644 (file)
index 0000000..1e5b6a4
--- /dev/null
@@ -0,0 +1,112 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if !defined(X86CPU_H)
+# define X86CPU_H
+
+# if defined(OPUS_X86_MAY_HAVE_SSE)
+#  define MAY_HAVE_SSE(name) name ## _sse
+# else
+#  define MAY_HAVE_SSE(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+#  define MAY_HAVE_SSE2(name) name ## _sse2
+# else
+#  define MAY_HAVE_SSE2(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#  define MAY_HAVE_SSE4_1(name) name ## _sse4_1
+# else
+#  define MAY_HAVE_SSE4_1(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_AVX2)
+#  define MAY_HAVE_AVX2(name) name ## _avx2
+# else
+#  define MAY_HAVE_AVX2(name) name ## _c
+# endif
+
+# if defined(OPUS_HAVE_RTCD) && \
+  ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+  (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+  (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+int opus_select_arch(void);
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+#  include "opus_defines.h"
+
+/*MOVD should not impose any alignment restrictions, but the C standard does,
+   and UBSan will report errors if we actually make unaligned accesses.
+  Use this to work around those restrictions (which should hopefully all get
+   optimized to a single MOVD instruction).
+  GCC implemented _mm_loadu_si32() since GCC 11; HOWEVER, there is a bug!
+  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99754
+  LLVM implemented _mm_loadu_si32() since Clang 8.0, however the
+   __clang_major__ version number macro is unreliable, as vendors
+   (specifically, Apple) will use different numbering schemes than upstream.
+  Clang's advice is "use feature detection", but they do not provide feature
+   detection support for specific SIMD functions.
+  We follow the approach from the SIMDe project and instead detect unrelated
+   features that should be available in the version we want (see
+   <https://github.com/simd-everywhere/simde/blob/master/simde/simde-detect-clang.h>).*/
+#  if defined(__clang__)
+#   if __has_warning("-Wextra-semi-stmt") || \
+ __has_builtin(__builtin_rotateleft32)
+#    define OPUS_CLANG_8 (1)
+#   endif
+#  endif
+#  if !defined(_MSC_VER) && !OPUS_GNUC_PREREQ(11,3) && !defined(OPUS_CLANG_8)
+#   include <string.h>
+#   include <emmintrin.h>
+
+#   ifdef _mm_loadu_si32
+#    undef _mm_loadu_si32
+#   endif
+#   define _mm_loadu_si32 WORKAROUND_mm_loadu_si32
+static inline __m128i WORKAROUND_mm_loadu_si32(void const* mem_addr) {
+  int val;
+  memcpy(&val, mem_addr, sizeof(val));
+  return _mm_cvtsi32_si128(val);
+}
+#  elif defined(_MSC_VER)
+    /* MSVC needs this for _mm_loadu_si32 */
+#   include <immintrin.h>
+#  endif
+
+#  define OP_CVTEPI8_EPI32_M32(x) \
+ (_mm_cvtepi8_epi32(_mm_loadu_si32(x)))
+
+#  define OP_CVTEPI16_EPI32_M64(x) \
+ (_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(void*)(x))))
+
+# endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.ps1 b/code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.ps1
new file mode 100644 (file)
index 0000000..f6f129c
--- /dev/null
@@ -0,0 +1,112 @@
+# PowerShell 清理脚本:清理所有编译产物和中间文件,仅保留源码\r
+# 使用方式: .\clean_all.ps1\r
+\r
+$ErrorActionPreference = "Stop"\r
+\r
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\r
+\r
+Write-Host "=========================================="\r
+Write-Host "清理编译产物和中间文件"\r
+Write-Host "=========================================="\r
+Write-Host "工作目录: $ScriptDir"\r
+Write-Host ""\r
+\r
+$CleanedCount = 0\r
+\r
+function Clean-File {\r
+    param([string]$Path)\r
+    \r
+    if (Test-Path $Path) {\r
+        Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue\r
+        Write-Host "  删除: $Path"\r
+        $script:CleanedCount++\r
+    }\r
+}\r
+\r
+# 清理所有 .o 文件\r
+Write-Host "清理对象文件 (.o)..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.o" -File -ErrorAction SilentlyContinue | ForEach-Object {\r
+    Clean-File $_.FullName\r
+}\r
+\r
+# 清理生成的库文件\r
+Write-Host ""\r
+Write-Host "清理库文件..."\r
+Clean-File (Join-Path $ScriptDir "libopus_min.a")\r
+# 清理符号链接或普通文件\r
+$libopusPath = Join-Path $ScriptDir "libopus.a"\r
+if (Test-Path $libopusPath) {\r
+       $item = Get-Item $libopusPath -ErrorAction SilentlyContinue\r
+       if ($item.LinkType -eq "SymbolicLink") {\r
+               Remove-Item -Path $libopusPath -Force -ErrorAction SilentlyContinue\r
+               Write-Host "  删除: $libopusPath (符号链接)"\r
+               $CleanedCount++\r
+       } else {\r
+               Clean-File $libopusPath\r
+       }\r
+}\r
+\r
+# 清理可执行文件\r
+Write-Host ""\r
+Write-Host "清理可执行文件..."\r
+Clean-File (Join-Path $ScriptDir "opus_frame_to_pcm")\r
+Clean-File (Join-Path $ScriptDir "opus_frame_to_pcm.exe")\r
+\r
+# 清理测试输出文件\r
+Write-Host ""\r
+Write-Host "清理测试输出文件..."\r
+Clean-File (Join-Path $ScriptDir "test_output.pcm")\r
+Clean-File (Join-Path $ScriptDir "test_output_new.pcm")\r
+Clean-File (Join-Path $ScriptDir "test_frame.opus")\r
+\r
+# 清理 Makefile 生成的临时文件\r
+Write-Host ""\r
+Write-Host "清理 Makefile 临时文件..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.d" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter ".depend" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.su" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.gcda" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.gcno" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+\r
+# 清理可能的备份文件\r
+Write-Host ""\r
+Write-Host "清理备份文件..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*~" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.bak" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.swp" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.tmp" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+\r
+# 清理空目录(除了源码目录结构)\r
+Write-Host ""\r
+Write-Host "清理空目录..."\r
+$EmptyDirs = Get-ChildItem -Path $ScriptDir -Recurse -Directory -ErrorAction SilentlyContinue | \r
+    Where-Object { (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count -eq 0 }\r
+$EmptyDirs | ForEach-Object {\r
+    # 只删除非源码目录的空目录\r
+    $relPath = $_.FullName.Replace($ScriptDir, "").TrimStart("\")\r
+    if ($relPath -notmatch "^src_lib" -and $relPath -notmatch "^celt" -and $relPath -notmatch "^silk" -and $relPath -notmatch "^include") {\r
+        try {\r
+            Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue\r
+        } catch {\r
+            # 忽略错误\r
+        }\r
+    }\r
+}\r
+\r
+Write-Host ""\r
+Write-Host "=========================================="\r
+if ($CleanedCount -gt 0) {\r
+    Write-Host "清理完成!共清理 $CleanedCount 个文件/目录"\r
+} else {\r
+    Write-Host "没有找到需要清理的文件"\r
+}\r
+Write-Host "=========================================="\r
+Write-Host ""\r
+Write-Host "保留的文件类型:"\r
+Write-Host "  - 源码文件 (.c)"\r
+Write-Host "  - 头文件 (.h)"\r
+Write-Host "  - 配置文件 (config.h)"\r
+Write-Host "  - 脚本文件 (.sh, .ps1, .bat)"\r
+Write-Host "  - Makefile 文件"\r
+Write-Host "  - 文档文件 (.md)"\r
+Write-Host ""\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.sh b/code/sdk/zhihui/test_opus_frame_to_pcm/clean_all.sh
new file mode 100644 (file)
index 0000000..e9f474e
--- /dev/null
@@ -0,0 +1,99 @@
+#!/bin/bash
+# 清理脚本:清理所有编译产物和中间文件,仅保留源码
+# 使用方式: ./clean_all.sh
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+echo "=========================================="
+echo "清理编译产物和中间文件"
+echo "=========================================="
+echo "工作目录: $SCRIPT_DIR"
+echo ""
+
+# 计数器
+CLEANED_COUNT=0
+
+# 清理函数
+clean_file() {
+    if [ -f "$1" ] || [ -d "$1" ]; then
+        rm -rf "$1"
+        echo "  删除: $1"
+        CLEANED_COUNT=$((CLEANED_COUNT + 1))
+    fi
+}
+
+# 清理所有 .o 文件
+echo "清理对象文件 (.o)..."
+find "$SCRIPT_DIR" -type f -name "*.o" -print0 | while IFS= read -r -d '' file; do
+    clean_file "$file"
+done
+
+# 清理生成的库文件
+echo ""
+echo "清理库文件..."
+clean_file "$SCRIPT_DIR/libopus_min.a"
+# 清理符号链接或普通文件
+if [ -L "$SCRIPT_DIR/libopus.a" ]; then
+       rm -f "$SCRIPT_DIR/libopus.a"
+       echo "  删除: $SCRIPT_DIR/libopus.a (符号链接)"
+       CLEANED_COUNT=$((CLEANED_COUNT + 1))
+elif [ -f "$SCRIPT_DIR/libopus.a" ]; then
+       clean_file "$SCRIPT_DIR/libopus.a"
+fi
+
+# 清理可执行文件
+echo ""
+echo "清理可执行文件..."
+clean_file "$SCRIPT_DIR/opus_frame_to_pcm"
+clean_file "$SCRIPT_DIR/opus_frame_to_pcm.exe"
+
+# 清理测试输出文件
+echo ""
+echo "清理测试输出文件..."
+clean_file "$SCRIPT_DIR/test_output.pcm"
+clean_file "$SCRIPT_DIR/test_output_new.pcm"
+clean_file "$SCRIPT_DIR/test_frame.opus"
+
+# 清理 Makefile 生成的临时文件
+echo ""
+echo "清理 Makefile 临时文件..."
+find "$SCRIPT_DIR" -type f -name "*.d" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name ".depend" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.su" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.gcda" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.gcno" -delete 2>/dev/null || true
+
+# 清理可能的备份文件
+echo ""
+echo "清理备份文件..."
+find "$SCRIPT_DIR" -type f -name "*~" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.bak" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.swp" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.tmp" -delete 2>/dev/null || true
+
+# 清理空目录(除了源码目录)
+echo ""
+echo "清理空目录..."
+find "$SCRIPT_DIR/src_lib" -type d -empty -delete 2>/dev/null || true
+find "$SCRIPT_DIR/celt" -type d -empty -delete 2>/dev/null || true
+find "$SCRIPT_DIR/silk" -type d -empty -delete 2>/dev/null || true
+
+echo ""
+echo "=========================================="
+if [ $CLEANED_COUNT -gt 0 ]; then
+    echo "清理完成!共清理 $CLEANED_COUNT 个文件/目录"
+else
+    echo "没有找到需要清理的文件"
+fi
+echo "=========================================="
+echo ""
+echo "保留的文件类型:"
+echo "  - 源码文件 (.c)"
+echo "  - 头文件 (.h)"
+echo "  - 配置文件 (config.h)"
+echo "  - 脚本文件 (.sh, .ps1, .bat)"
+echo "  - Makefile 文件"
+echo "  - 文档文件 (.md)"
+echo ""
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/config.h b/code/sdk/zhihui/test_opus_frame_to_pcm/config.h
new file mode 100644 (file)
index 0000000..14063ac
--- /dev/null
@@ -0,0 +1,252 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Get CPU Info by asm method */
+#define CPU_INFO_BY_ASM 1
+
+/* Get CPU Info by c method */
+/* #undef CPU_INFO_BY_C */
+
+/* Custom modes */
+/* #undef CUSTOM_MODES */
+
+/* Disable DNN debug float */
+#define DISABLE_DEBUG_FLOAT 1
+
+/* Disable dot product instructions */
+/* #undef DISABLE_DOT_PROD */
+
+/* Do not build the float API */
+/* #undef DISABLE_FLOAT_API */
+
+/* Disable bitstream fixes from RFC 8251 */
+/* #undef DISABLE_UPDATE_DRAFT */
+
+/* Assertions */
+/* #undef ENABLE_ASSERTIONS */
+
+/* Deep PLC */
+/* #undef ENABLE_DEEP_PLC */
+
+/* DRED */
+/* #undef ENABLE_DRED */
+
+/* Hardening */
+#define ENABLE_HARDENING 1
+
+/* LOSSGEN */
+/* #undef ENABLE_LOSSGEN */
+
+/* Opus custom API */
+/* #undef ENABLE_OPUS_CUSTOM_API */
+
+/* Enable Opus Speech Coding Enhancement */
+/* #undef ENABLE_OSCE */
+
+/* Enable Opus Speech Coding Enhancement Blind BWE */
+/* #undef ENABLE_OSCE_BWE */
+
+/* Enable dumping of OSCE training data */
+/* #undef ENABLE_OSCE_TRAINING_DATA */
+
+/* Scalable quality extension */
+/* #undef ENABLE_QEXT */
+
+/* 24-bit internal resolution for fixed-point */
+#define ENABLE_RES24 1
+
+/* Debug fixed-point implementation */
+/* #undef FIXED_DEBUG */
+
+/* Compile as fixed-point (for machines without a fast enough FPU) */
+/* #undef FIXED_POINT */
+
+/* Float approximations */
+#define FLOAT_APPROX 1
+
+/* Fuzzing */
+/* #undef FUZZING */
+
+/* Define to 1 if you have the <alloca.h> header file. */
+/* #undef HAVE_ALLOCA_H */
+
+/* NE10 library is installed on host. Make sure it is on target! */
+/* #undef HAVE_ARM_NE10 */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `elf_aux_info' function. */
+/* #undef HAVE_ELF_AUX_INFO */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `lrint' function. */
+#define HAVE_LRINT 1
+
+/* Define to 1 if you have the `lrintf' function. */
+#define HAVE_LRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `__malloc_hook' function. */
+#define HAVE___MALLOC_HOOK 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Make use of ARM asm optimization */
+/* #undef OPUS_ARM_ASM */
+
+/* Use generic ARMv4 inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_ASM */
+
+/* Use ARMv5E inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_EDSP */
+
+/* Use ARMv6 inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_MEDIA */
+
+/* Use ARM NEON inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_NEON */
+
+/* Compiler supports Aarch64 DOTPROD Intrinsics */
+/* #undef OPUS_ARM_MAY_HAVE_DOTPROD */
+
+/* Define if assembler supports EDSP instructions */
+/* #undef OPUS_ARM_MAY_HAVE_EDSP */
+
+/* Define if assembler supports ARMv6 media instructions */
+/* #undef OPUS_ARM_MAY_HAVE_MEDIA */
+
+/* Define if compiler supports NEON instructions */
+/* #undef OPUS_ARM_MAY_HAVE_NEON */
+
+/* Compiler supports ARMv7/Aarch64 Neon Intrinsics */
+/* #undef OPUS_ARM_MAY_HAVE_NEON_INTR */
+
+/* Define if binary requires Aarch64 Neon Intrinsics */
+/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */
+
+/* Define if binary requires Aarch64 dotprod Intrinsics */
+/* #undef OPUS_ARM_PRESUME_DOTPROD */
+
+/* Define if binary requires EDSP instruction support */
+/* #undef OPUS_ARM_PRESUME_EDSP */
+
+/* Define if binary requires ARMv6 media instruction support */
+/* #undef OPUS_ARM_PRESUME_MEDIA */
+
+/* Define if binary requires NEON instruction support */
+/* #undef OPUS_ARM_PRESUME_NEON */
+
+/* Define if binary requires NEON intrinsics support */
+/* #undef OPUS_ARM_PRESUME_NEON_INTR */
+
+/* This is a build of OPUS */
+#define OPUS_BUILD /**/
+
+/* Run bit-exactness checks between optimized and C implementations */
+/* #undef OPUS_CHECK_ASM */
+
+/* Use run-time CPU capabilities detection */
+#define OPUS_HAVE_RTCD 1
+
+/* Compiler supports X86 AVX2 Intrinsics */
+#define OPUS_X86_MAY_HAVE_AVX2 1
+
+/* Compiler supports X86 SSE Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE 1
+
+/* Compiler supports X86 SSE2 Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE2 1
+
+/* Compiler supports X86 SSE4.1 Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE4_1 1
+
+/* Define if binary requires AVX2 intrinsics support */
+/* #undef OPUS_X86_PRESUME_AVX2 */
+
+/* Define if binary requires SSE intrinsics support */
+#define OPUS_X86_PRESUME_SSE 1
+
+/* Define if binary requires SSE2 intrinsics support */
+#define OPUS_X86_PRESUME_SSE2 1
+
+/* Define if binary requires SSE4.1 intrinsics support */
+/* #undef OPUS_X86_PRESUME_SSE4_1 */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opus@xiph.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "opus"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "opus 1.6.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "opus"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.6.1"
+
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+   required in a freestanding environment). This macro is provided for
+   backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Make use of alloca */
+/* #undef USE_ALLOCA */
+
+/* Use C99 variable-size arrays */
+#define VAR_ARRAYS 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+   nothing if this is not supported.  Do not define if restrict is
+   supported directly.  */
+#define restrict __restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+   __restrict__, even though the corresponding Sun C compiler ends up with
+   "#define restrict _Restrict" or "#define restrict __restrict__" in the
+   previous line.  Perhaps some future version of Sun C++ will work with
+   restrict; if so, hopefully it defines __RESTRICT like Sun C does.  */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/copy_sources.sh b/code/sdk/zhihui/test_opus_frame_to_pcm/copy_sources.sh
new file mode 100644 (file)
index 0000000..2fe846a
--- /dev/null
@@ -0,0 +1,309 @@
+#!/bin/bash
+# Script to copy necessary source files for building minimal decoder library
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+echo "=========================================="
+echo "Copying Opus Decoder Source Files"
+echo "=========================================="
+echo "Project root: $PROJECT_ROOT"
+echo "Target directory: $SCRIPT_DIR"
+echo ""
+
+# Create directories
+mkdir -p "$SCRIPT_DIR/src_lib"
+mkdir -p "$SCRIPT_DIR/celt"
+mkdir -p "$SCRIPT_DIR/celt/x86"
+mkdir -p "$SCRIPT_DIR/silk"
+mkdir -p "$SCRIPT_DIR/silk/float"
+mkdir -p "$SCRIPT_DIR/silk/x86"
+mkdir -p "$SCRIPT_DIR/include"
+
+echo "Created directory structure"
+echo ""
+
+# Copy Opus API layer sources (decoder only)
+echo "Copying Opus API sources..."
+OPUS_SRC_FILES=(
+       "src/opus.c"
+       "src/opus_decoder.c"
+       "src/opus_multistream_decoder.c"
+       "src/opus_projection_decoder.c"
+       "src/extensions.c"
+       "src/repacketizer.c"
+       "src/mapping_matrix.c"
+)
+
+for file in "${OPUS_SRC_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/src_lib/"
+               echo "  Copied: $file"
+       else
+               echo "  Warning: $file not found"
+       fi
+done
+
+# Copy Opus private header
+if [ -f "$PROJECT_ROOT/src/opus_private.h" ]; then
+       cp "$PROJECT_ROOT/src/opus_private.h" "$SCRIPT_DIR/src_lib/"
+       echo "  Copied: src/opus_private.h"
+fi
+
+echo ""
+
+# Copy CELT sources
+echo "Copying CELT sources..."
+CELT_SRC_FILES=(
+       "celt/bands.c"
+       "celt/celt.c"
+       "celt/celt_decoder.c"
+       "celt/cwrs.c"
+       "celt/entcode.c"
+       "celt/entdec.c"
+       "celt/entenc.c"
+       "celt/kiss_fft.c"
+       "celt/laplace.c"
+       "celt/mathops.c"
+       "celt/mdct.c"
+       "celt/modes.c"
+       "celt/pitch.c"
+       "celt/celt_lpc.c"
+       "celt/quant_bands.c"
+       "celt/rate.c"
+       "celt/vq.c"
+)
+
+for file in "${CELT_SRC_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/celt/"
+               echo "  Copied: $file"
+       else
+               echo "  Warning: $file not found"
+       fi
+done
+
+# Copy CELT x86 optimization
+echo "Copying CELT x86 optimization..."
+CELT_X86_FILES=(
+       "celt/x86/x86cpu.c"
+       "celt/x86/x86_celt_map.c"
+       "celt/x86/pitch_sse.c"
+       "celt/x86/pitch_sse2.c"
+       "celt/x86/vq_sse2.c"
+       "celt/x86/celt_lpc_sse4_1.c"
+       "celt/x86/pitch_sse4_1.c"
+       "celt/x86/pitch_avx.c"
+)
+
+for file in "${CELT_X86_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/celt/x86/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy CELT headers
+echo "Copying CELT headers..."
+if [ -d "$PROJECT_ROOT/celt" ]; then
+       find "$PROJECT_ROOT/celt" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/celt/" \;
+       echo "  Copied CELT headers"
+fi
+
+echo ""
+
+# Copy SILK core decoder sources
+echo "Copying SILK decoder sources..."
+SILK_CORE_FILES=(
+       "silk/dec_API.c"
+       "silk/init_decoder.c"
+       "silk/decode_core.c"
+       "silk/decode_frame.c"
+       "silk/decode_parameters.c"
+       "silk/decode_indices.c"
+       "silk/decode_pulses.c"
+       "silk/decoder_set_fs.c"
+)
+
+for file in "${SILK_CORE_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK signal processing
+SILK_SIGNAL_FILES=(
+       "silk/CNG.c"
+       "silk/PLC.c"
+       "silk/resampler.c"
+       "silk/resampler_down2_3.c"
+       "silk/resampler_down2.c"
+       "silk/resampler_private_AR2.c"
+       "silk/resampler_private_down_FIR.c"
+       "silk/resampler_private_IIR_FIR.c"
+       "silk/resampler_private_up2_HQ.c"
+       "silk/resampler_rom.c"
+       "silk/biquad_alt.c"
+       "silk/bwexpander_32.c"
+       "silk/bwexpander.c"
+       "silk/LP_variable_cutoff.c"
+       "silk/HP_variable_cutoff.c"
+)
+
+for file in "${SILK_SIGNAL_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK NLSF processing
+SILK_NLSF_FILES=(
+       "silk/NLSF_decode.c"
+       "silk/NLSF_unpack.c"
+       "silk/NLSF2A.c"
+       "silk/NLSF_stabilize.c"
+       "silk/A2NLSF.c"
+       "silk/NLSF_VQ_weights_laroia.c"
+       "silk/table_LSF_cos.c"
+       "silk/LPC_inv_pred_gain.c"
+)
+
+for file in "${SILK_NLSF_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK stereo processing
+SILK_STEREO_FILES=(
+       "silk/stereo_MS_to_LR.c"
+       "silk/stereo_decode_pred.c"
+       "silk/stereo_find_predictor.c"
+)
+
+for file in "${SILK_STEREO_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK tables
+SILK_TABLE_FILES=(
+       "silk/tables_gain.c"
+       "silk/tables_LTP.c"
+       "silk/tables_NLSF_CB_NB_MB.c"
+       "silk/tables_NLSF_CB_WB.c"
+       "silk/tables_other.c"
+       "silk/tables_pitch_lag.c"
+       "silk/tables_pulses_per_block.c"
+       "silk/pitch_est_tables.c"
+)
+
+for file in "${SILK_TABLE_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK helper functions
+SILK_HELPER_FILES=(
+       "silk/code_signs.c"
+       "silk/interpolate.c"
+       "silk/shell_coder.c"
+       "silk/decode_pitch.c"
+       "silk/inner_prod_aligned.c"
+       "silk/lin2log.c"
+       "silk/log2lin.c"
+       "silk/LPC_analysis_filter.c"
+       "silk/LPC_fit.c"
+       "silk/sigm_Q15.c"
+       "silk/sort.c"
+       "silk/sum_sqr_shift.c"
+       "silk/gain_quant.c"
+)
+
+for file in "${SILK_HELPER_FILES[@]}"; do
+       if [ -f "$PROJECT_ROOT/$file" ]; then
+               cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+               echo "  Copied: $file"
+       fi
+done
+
+# Copy SILK float implementation
+echo "Copying SILK float implementation..."
+if [ -d "$PROJECT_ROOT/silk/float" ]; then
+       find "$PROJECT_ROOT/silk/float" -name "*.c" -exec cp {} "$SCRIPT_DIR/silk/float/" \;
+       echo "  Copied SILK float sources"
+fi
+
+# Copy SILK x86 optimization
+if [ -d "$PROJECT_ROOT/silk/x86" ]; then
+       if [ -f "$PROJECT_ROOT/silk/x86/x86_silk_map.c" ]; then
+               cp "$PROJECT_ROOT/silk/x86/x86_silk_map.c" "$SCRIPT_DIR/silk/x86/"
+               echo "  Copied: silk/x86/x86_silk_map.c"
+       fi
+fi
+
+# Copy SILK headers
+echo "Copying SILK headers..."
+if [ -d "$PROJECT_ROOT/silk" ]; then
+       find "$PROJECT_ROOT/silk" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/silk/" \;
+       echo "  Copied SILK headers"
+fi
+
+# Copy additional headers
+echo ""
+echo "Copying additional headers..."
+# Opus API headers
+if [ -f "$PROJECT_ROOT/include/opus_custom.h" ]; then
+       cp "$PROJECT_ROOT/include/opus_custom.h" "$SCRIPT_DIR/include/"
+       echo "  Copied: include/opus_custom.h"
+fi
+if [ -f "$PROJECT_ROOT/include/opus_multistream.h" ]; then
+       cp "$PROJECT_ROOT/include/opus_multistream.h" "$SCRIPT_DIR/include/"
+       echo "  Copied: include/opus_multistream.h"
+fi
+if [ -f "$PROJECT_ROOT/include/opus_projection.h" ]; then
+       cp "$PROJECT_ROOT/include/opus_projection.h" "$SCRIPT_DIR/include/"
+       echo "  Copied: include/opus_projection.h"
+fi
+
+# Copy src headers
+if [ -d "$PROJECT_ROOT/src" ]; then
+       find "$PROJECT_ROOT/src" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/src_lib/" \;
+       echo "  Copied src headers"
+fi
+
+# Copy x86 headers
+if [ -d "$PROJECT_ROOT/celt/x86" ]; then
+       find "$PROJECT_ROOT/celt/x86" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/celt/x86/" \;
+       echo "  Copied CELT x86 headers"
+fi
+if [ -d "$PROJECT_ROOT/silk/x86" ]; then
+       find "$PROJECT_ROOT/silk/x86" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/silk/x86/" \;
+       echo "  Copied SILK x86 headers"
+fi
+
+# Copy config.h from main project
+if [ -f "$PROJECT_ROOT/config.h" ]; then
+       cp "$PROJECT_ROOT/config.h" "$SCRIPT_DIR/config.h"
+       echo "  Copied: config.h"
+fi
+
+echo ""
+echo "=========================================="
+echo "Source files copied successfully!"
+echo "=========================================="
+echo ""
+echo "Next steps:"
+echo "  1. Review copied files"
+echo "  2. Run: make -f Makefile.libopus"
+echo "  3. This will create libopus_min.a"
+echo ""
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus.h
new file mode 100644 (file)
index 0000000..802be9f
--- /dev/null
@@ -0,0 +1,1175 @@
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus.h
+ * @brief Opus reference implementation API
+ */
+
+#ifndef OPUS_H
+#define OPUS_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @mainpage Opus
+ *
+ * The Opus codec is designed for interactive speech and audio transmission over the Internet.
+ * It is designed by the IETF Codec Working Group and incorporates technology from
+ * Skype's SILK codec and Xiph.Org's CELT codec.
+ *
+ * The Opus codec is designed to handle a wide range of interactive audio applications,
+ * including Voice over IP, videoconferencing, in-game chat, and even remote live music
+ * performances. It can scale from low bit-rate narrowband speech to very high quality
+ * stereo music. Its main features are:
+
+ * @li Sampling rates from 8 to 48 kHz
+ * @li Bit-rates from 6 kb/s to 510 kb/s
+ * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
+ * @li Audio bandwidth from narrowband to full-band
+ * @li Support for speech and music
+ * @li Support for mono and stereo
+ * @li Support for multichannel (up to 255 channels)
+ * @li Frame sizes from 2.5 ms to 60 ms
+ * @li Good loss robustness and packet loss concealment (PLC)
+ * @li Floating point and fixed-point implementation
+ *
+ * Documentation sections:
+ * @li @ref opus_encoder
+ * @li @ref opus_decoder
+ * @li @ref opus_repacketizer
+ * @li @ref opus_multistream
+ * @li @ref opus_libinfo
+ * @li @ref opus_custom
+ */
+
+/** @defgroup opus_encoder Opus Encoder
+  * @{
+  *
+  * @brief This page describes the process and functions used to encode Opus.
+  *
+  * Since Opus is a stateful codec, the encoding process starts with creating an encoder
+  * state. This can be done with:
+  *
+  * @code
+  * int          error;
+  * OpusEncoder *enc;
+  * enc = opus_encoder_create(Fs, channels, application, &error);
+  * @endcode
+  *
+  * From this point, @c enc can be used for encoding an audio stream. An encoder state
+  * @b must @b not be used for more than one stream at the same time. Similarly, the encoder
+  * state @b must @b not be re-initialized for each frame.
+  *
+  * While opus_encoder_create() allocates memory for the state, it's also possible
+  * to initialize pre-allocated memory:
+  *
+  * @code
+  * int          size;
+  * int          error;
+  * OpusEncoder *enc;
+  * size = opus_encoder_get_size(channels);
+  * enc = malloc(size);
+  * error = opus_encoder_init(enc, Fs, channels, application);
+  * @endcode
+  *
+  * where opus_encoder_get_size() returns the required size for the encoder state. Note that
+  * future versions of this code may change the size, so no assumptions should be made about it.
+  *
+  * The encoder state is always continuous in memory and only a shallow copy is sufficient
+  * to copy it (e.g. memcpy())
+  *
+  * It is possible to change some of the encoder's settings using the opus_encoder_ctl()
+  * interface. All these settings already default to the recommended value, so they should
+  * only be changed when necessary. The most common settings one may want to change are:
+  *
+  * @code
+  * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
+  * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
+  * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
+  * @endcode
+  *
+  * where
+  *
+  * @arg bitrate is in bits per second (b/s)
+  * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
+  * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
+  *
+  * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
+  *
+  * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
+  * @code
+  * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
+  * @endcode
+  *
+  * where
+  * <ul>
+  * <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
+  * <li>frame_size is the duration of the frame in samples (per channel)</li>
+  * <li>packet is the byte array to which the compressed data is written</li>
+  * <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
+  *     Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li>
+  * </ul>
+  *
+  * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
+  * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
+  * is 2 bytes or less, then the packet does not need to be transmitted (DTX).
+  *
+  * Once the encoder state if no longer needed, it can be destroyed with
+  *
+  * @code
+  * opus_encoder_destroy(enc);
+  * @endcode
+  *
+  * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
+  * then no action is required aside from potentially freeing the memory that was manually
+  * allocated for it (calling free(enc) for the example above)
+  *
+  */
+
+/** Opus encoder state.
+  * This contains the complete state of an Opus encoder.
+  * It is position independent and can be freely copied.
+  * @see opus_encoder_create,opus_encoder_init
+  */
+typedef struct OpusEncoder OpusEncoder;
+
+/** Gets the size of an <code>OpusEncoder</code> structure.
+  * @param[in] channels <tt>int</tt>: Number of channels.
+  *                                   This must be 1 or 2.
+  * @returns The size in bytes.
+  * @note Since this function does not take the application as input, it will overestimate
+  * the size required for OPUS_APPLICATION_RESTRICTED_SILK and OPUS_APPLICATION_RESTRICTED_CELT.
+  * That is generally not a problem, except when trying to know the size to use for a copy.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
+
+/**
+ */
+
+/** Allocates and initializes an encoder state.
+ * There are three coding modes:
+ *
+ * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
+ *    signals. It enhances the  input signal by high-pass filtering and
+ *    emphasizing formants and harmonics. Optionally  it includes in-band
+ *    forward error correction to protect against packet loss. Use this
+ *    mode for typical VoIP applications. Because of the enhancement,
+ *    even at high bitrates the output may sound different from the input.
+ *
+ * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
+ *    non-voice signals like music. Use this mode for music and mixed
+ *    (music/voice) content, broadcast, and applications requiring less
+ *    than 15 ms of coding delay.
+ *
+ * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
+ *    disables the speech-optimized mode in exchange for slightly reduced delay.
+ *    This mode can only be set on an newly initialized or freshly reset encoder
+ *    because it changes the codec delay.
+ *
+ * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+ *                                     This must be one of 8000, 12000, 16000,
+ *                                     24000, or 48000.
+ * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
+ * @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @param [out] error <tt>int*</tt>: @ref opus_errorcodes
+ * @note Regardless of the sampling rate and number channels selected, the Opus encoder
+ * can switch to a lower audio bandwidth or number of channels if the bitrate
+ * selected is too low. This also means that it is safe to always use 48 kHz stereo input
+ * and let the encoder optimize the encoding.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
+    opus_int32 Fs,
+    int channels,
+    int application,
+    int *error
+);
+
+/** Initializes a previously allocated encoder state
+  * The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
+  * This is intended for applications which use their own allocator instead of malloc.
+  * @see opus_encoder_create(),opus_encoder_get_size()
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+ *                                      This must be one of 8000, 12000, 16000,
+ *                                      24000, or 48000.
+  * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
+  * @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+  * @retval #OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_encoder_init(
+    OpusEncoder *st,
+    opus_int32 Fs,
+    int channels,
+    int application
+) OPUS_ARG_NONNULL(1);
+
+/** Encodes an Opus frame.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+  *                                      input signal.
+  *                                      This must be an Opus frame size for
+  *                                      the encoder's sampling rate.
+  *                                      For example, at 48 kHz the permitted
+  *                                      values are 120, 240, 480, 960, 1920,
+  *                                      and 2880.
+  *                                      Passing in a duration of less than
+  *                                      10 ms (480 samples at 48 kHz) will
+  *                                      prevent the encoder from using the LPC
+  *                                      or hybrid modes.
+  * @param [out] data <tt>unsigned char*</tt>: Output payload.
+  *                                            This must contain storage for at
+  *                                            least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
+    OpusEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes an Opus frame.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int32*</tt>: Input signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length is frame_size*channels*sizeof(opus_int32)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+  *                                      input signal.
+  *                                      This must be an Opus frame size for
+  *                                      the encoder's sampling rate.
+  *                                      For example, at 48 kHz the permitted
+  *                                      values are 120, 240, 480, 960, 1920,
+  *                                      and 2880.
+  *                                      Passing in a duration of less than
+  *                                      10 ms (480 samples at 48 kHz) will
+  *                                      prevent the encoder from using the LPC
+  *                                      or hybrid modes.
+  * @param [out] data <tt>unsigned char*</tt>: Output payload.
+  *                                            This must contain storage for at
+  *                                            least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode24(
+    OpusEncoder *st,
+    const opus_int32 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes an Opus frame from floating point input.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
+  *          Samples with a range beyond +/-1.0 are supported but will
+  *          be clipped by decoders using the integer API and should
+  *          only be used if it is known that the far end supports
+  *          extended dynamic range.
+  *          length is frame_size*channels*sizeof(float)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+  *                                      input signal.
+  *                                      This must be an Opus frame size for
+  *                                      the encoder's sampling rate.
+  *                                      For example, at 48 kHz the permitted
+  *                                      values are 120, 240, 480, 960, 1920,
+  *                                      and 2880.
+  *                                      Passing in a duration of less than
+  *                                      10 ms (480 samples at 48 kHz) will
+  *                                      prevent the encoder from using the LPC
+  *                                      or hybrid modes.
+  * @param [out] data <tt>unsigned char*</tt>: Output payload.
+  *                                            This must contain storage for at
+  *                                            least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
+    OpusEncoder *st,
+    const float *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create().
+  * @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
+  */
+OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
+
+/** Perform a CTL function on an Opus encoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @param st <tt>OpusEncoder*</tt>: Encoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls or
+  *                @ref opus_encoderctls.
+  * @see opus_genericctls
+  * @see opus_encoderctls
+  */
+OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+/**@}*/
+
+/** @defgroup opus_decoder Opus Decoder
+  * @{
+  *
+  * @brief This page describes the process and functions used to decode Opus.
+  *
+  * The decoding process also starts with creating a decoder
+  * state. This can be done with:
+  * @code
+  * int          error;
+  * OpusDecoder *dec;
+  * dec = opus_decoder_create(Fs, channels, &error);
+  * @endcode
+  * where
+  * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
+  * @li channels is the number of channels (1 or 2)
+  * @li error will hold the error code in case of failure (or #OPUS_OK on success)
+  * @li the return value is a newly created decoder state to be used for decoding
+  *
+  * While opus_decoder_create() allocates memory for the state, it's also possible
+  * to initialize pre-allocated memory:
+  * @code
+  * int          size;
+  * int          error;
+  * OpusDecoder *dec;
+  * size = opus_decoder_get_size(channels);
+  * dec = malloc(size);
+  * error = opus_decoder_init(dec, Fs, channels);
+  * @endcode
+  * where opus_decoder_get_size() returns the required size for the decoder state. Note that
+  * future versions of this code may change the size, so no assumptions should be made about it.
+  *
+  * The decoder state is always continuous in memory and only a shallow copy is sufficient
+  * to copy it (e.g. memcpy())
+  *
+  * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
+  * @code
+  * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
+  * @endcode
+  * where
+  *
+  * @li packet is the byte array containing the compressed data
+  * @li len is the exact number of bytes contained in the packet
+  * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
+  * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
+  *
+  * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
+  * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
+  * buffer is too small to hold the decoded audio.
+  *
+  * Opus is a stateful codec with overlapping blocks and as a result Opus
+  * packets are not coded independently of each other. Packets must be
+  * passed into the decoder serially and in the correct order for a correct
+  * decode. Lost packets can be replaced with loss concealment by calling
+  * the decoder with a null pointer and zero length for the missing packet.
+  *
+  * A single codec state may only be accessed from a single thread at
+  * a time and any required locking must be performed by the caller. Separate
+  * streams must be decoded with separate decoder states and can be decoded
+  * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
+  * defined.
+  *
+  */
+
+/** Opus decoder state.
+  * This contains the complete state of an Opus decoder.
+  * It is position independent and can be freely copied.
+  * @see opus_decoder_create,opus_decoder_init
+  */
+typedef struct OpusDecoder OpusDecoder;
+
+/** Opus DRED decoder.
+  * This contains the complete state of an Opus DRED decoder.
+  * It is position independent and can be freely copied.
+  * @see opus_dred_decoder_create,opus_dred_decoder_init
+  */
+typedef struct OpusDREDDecoder OpusDREDDecoder;
+
+
+/** Opus DRED state.
+  * This contains the complete state of an Opus DRED packet.
+  * It is position independent and can be freely copied.
+  * @see opus_dred_create,opus_dred_init
+  */
+typedef struct OpusDRED OpusDRED;
+
+/** Gets the size of an <code>OpusDecoder</code> structure.
+  * @param [in] channels <tt>int</tt>: Number of channels.
+  *                                    This must be 1 or 2.
+  * @returns The size in bytes.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
+
+/** Allocates and initializes a decoder state.
+  * @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz).
+  *                                     This must be one of 8000, 12000, 16000,
+  *                                     24000, or 48000.
+  * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
+  * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+  *
+  * Internally Opus stores data at 48000 Hz, so that should be the default
+  * value for Fs. However, the decoder can efficiently decode to buffers
+  * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
+  * data at the full sample rate, or knows the compressed data doesn't
+  * use the full frequency range, it can request decoding at a reduced
+  * rate. Likewise, the decoder is capable of filling in either mono or
+  * interleaved stereo pcm buffers, at the caller's request.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
+    opus_int32 Fs,
+    int channels,
+    int *error
+);
+
+/** Initializes a previously allocated decoder state.
+  * The state must be at least the size returned by opus_decoder_get_size().
+  * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
+  *                                     This must be one of 8000, 12000, 16000,
+  *                                     24000, or 48000.
+  * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
+  * @retval #OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_decoder_init(
+    OpusDecoder *st,
+    opus_int32 Fs,
+    int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Decode an Opus packet.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+  * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+  *  If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+  *  not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+  *  then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+  *  decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+  *  FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available, the frame is decoded as if it were lost.
+  * @returns Number of decoded samples per channel or @ref opus_errorcodes
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int16 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an Opus packet.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+  * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
+  *  is frame_size*channels*sizeof(opus_int32)
+  * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+  *  If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+  *  not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+  *  then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+  *  decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+  *  FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available, the frame is decoded as if it were lost.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode24(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int32 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an Opus packet with floating point output.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
+  * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(float)
+  * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+  *  If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+  *  not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+  *  then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+  *  decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+  *  FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available the frame is decoded as if it were lost.
+  * @returns Number of decoded samples per channel or @ref opus_errorcodes
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    float *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus decoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @param st <tt>OpusDecoder*</tt>: Decoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls or
+  *                @ref opus_decoderctls.
+  * @see opus_genericctls
+  * @see opus_decoderctls
+  */
+OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create().
+  * @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
+  */
+OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
+
+/** Gets the size of an <code>OpusDREDDecoder</code> structure.
+  * @returns The size in bytes.
+  */
+OPUS_EXPORT int opus_dred_decoder_get_size(void);
+
+/** Allocates and initializes an OpusDREDDecoder state.
+  * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_EXPORT OpusDREDDecoder *opus_dred_decoder_create(int *error);
+
+/** Initializes an <code>OpusDREDDecoder</code> state.
+  * @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be initialized.
+  */
+OPUS_EXPORT int opus_dred_decoder_init(OpusDREDDecoder *dec);
+
+/** Frees an <code>OpusDREDDecoder</code> allocated by opus_dred_decoder_create().
+  * @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be freed.
+  */
+OPUS_EXPORT void opus_dred_decoder_destroy(OpusDREDDecoder *dec);
+
+/** Perform a CTL function on an Opus DRED decoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @param dred_dec <tt>OpusDREDDecoder*</tt>: DRED Decoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls or
+  *                @ref opus_decoderctls.
+  * @see opus_genericctls
+  * @see opus_decoderctls
+  */
+OPUS_EXPORT int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...);
+
+/** Gets the size of an <code>OpusDRED</code> structure.
+  * @returns The size in bytes.
+  */
+OPUS_EXPORT int opus_dred_get_size(void);
+
+/** Allocates and initializes a DRED state.
+  * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_EXPORT OpusDRED *opus_dred_alloc(int *error);
+
+/** Frees an <code>OpusDRED</code> allocated by opus_dred_create().
+  * @param[in] dec <tt>OpusDRED*</tt>: State to be freed.
+  */
+OPUS_EXPORT void opus_dred_free(OpusDRED *dec);
+
+/** Decode an Opus DRED packet.
+  * @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
+  * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+  * @param [in] data <tt>char*</tt>: Input payload
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
+  * @param [in] max_dred_samples <tt>opus_int32</tt>: Maximum number of DRED samples that may be needed (if available in the packet).
+  * @param [in] sampling_rate <tt>opus_int32</tt>: Sampling rate used for max_dred_samples argument. Needs not match the actual sampling rate of the decoder.
+  * @param [out] dred_end <tt>opus_int32*</tt>: Number of non-encoded (silence) samples between the DRED timestamp and the last DRED sample.
+  * @param [in] defer_processing <tt>int</tt>: Flag (0 or 1). If set to one, the CPU-intensive part of the DRED decoding is deferred until opus_dred_process() is called.
+  * @returns Offset (positive) of the first decoded DRED samples, zero if no DRED is present, or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing) OPUS_ARG_NONNULL(1);
+
+/** Finish decoding an Opus DRED packet. The function only needs to be called if opus_dred_parse() was called with defer_processing=1.
+  * The source and destination will often be the same DRED state.
+  * @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
+  * @param [in] src <tt>OpusDRED*</tt>: Source DRED state to start the processing from.
+  * @param [out] dst <tt>OpusDRED*</tt>: Destination DRED state to store the updated state after processing.
+  * @returns @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
+
+/** Decode audio from an Opus DRED packet with 16-bit output.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+  * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+  * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+  *  frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
+
+/** Decode audio from an Opus DRED packet with 24-bit output.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+  * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+  * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+  *  frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size);
+
+/** Decode audio from an Opus DRED packet with floating point output.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+  * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+  * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(float)
+  * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+  *  frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size);
+
+
+/** Parse an opus packet into one or more frames.
+  * Opus_decode will perform this operation internally so most applications do
+  * not need to use this function.
+  * This function does not copy the frames, the returned pointers are pointers into
+  * the input packet.
+  * @param [in] data <tt>char*</tt>: Opus packet to be parsed
+  * @param [in] len <tt>opus_int32</tt>: size of data
+  * @param [out] out_toc <tt>char*</tt>: TOC pointer
+  * @param [out] frames <tt>char*[48]</tt> encapsulated frames
+  * @param [out] size <tt>opus_int16[48]</tt> sizes of the encapsulated frames
+  * @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
+  * @returns number of frames
+  */
+OPUS_EXPORT int opus_packet_parse(
+   const unsigned char *data,
+   opus_int32 len,
+   unsigned char *out_toc,
+   const unsigned char *frames[48],
+   opus_int16 size[48],
+   int *payload_offset
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
+
+/** Gets the bandwidth of an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet
+  * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
+  * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
+  * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
+  * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
+  * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples per frame from an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet.
+  *                                  This must contain at least one byte of
+  *                                  data.
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
+  *                                     This must be a multiple of 400, or
+  *                                     inaccurate results will be returned.
+  * @returns Number of samples per frame.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of channels from an Opus packet.
+  * @param [in] data <tt>char*</tt>: Opus packet
+  * @returns Number of channels
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of frames in an Opus packet.
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @returns Number of frames
+  * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples of an Opus packet.
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
+  *                                     This must be a multiple of 400, or
+  *                                     inaccurate results will be returned.
+  * @returns Number of samples
+  * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Checks whether an Opus packet has LBRR.
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @returns 1 is LBRR is present, 0 otherwise
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len);
+
+/** Gets the number of samples of an Opus packet.
+  * @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] packet <tt>char*</tt>: Opus packet
+  * @param [in] len <tt>opus_int32</tt>: Length of packet
+  * @returns Number of samples
+  * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+  * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
+  * the signal is already in that range, nothing is done. If there are values
+  * outside of [-1,1], then the signal is clipped as smoothly as possible to
+  * both fit in the range and avoid creating excessive distortion in the
+  * process.
+  * @param [in,out] pcm <tt>float*</tt>: Input PCM and modified PCM
+  * @param [in] frame_size <tt>int</tt> Number of samples per channel to process
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @param [in,out] softclip_mem <tt>float*</tt>: State memory for the soft clipping process (one float per channel, initialized to zero)
+  */
+OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
+
+
+/**@}*/
+
+/** @defgroup opus_repacketizer Repacketizer
+  * @{
+  *
+  * The repacketizer can be used to merge multiple Opus packets into a single
+  * packet or alternatively to split Opus packets that have previously been
+  * merged. Splitting valid Opus packets is always guaranteed to succeed,
+  * whereas merging valid packets only succeeds if all frames have the same
+  * mode, bandwidth, and frame size, and when the total duration of the merged
+  * packet is no more than 120 ms. The 120 ms limit comes from the
+  * specification and limits decoder memory requirements at a point where
+  * framing overhead becomes negligible.
+  *
+  * The repacketizer currently only operates on elementary Opus
+  * streams. It will not manipulate multistream packets successfully, except in
+  * the degenerate case where they consist of data from a single stream.
+  *
+  * The repacketizing process starts with creating a repacketizer state, either
+  * by calling opus_repacketizer_create() or by allocating the memory yourself,
+  * e.g.,
+  * @code
+  * OpusRepacketizer *rp;
+  * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
+  * if (rp != NULL)
+  *     opus_repacketizer_init(rp);
+  * @endcode
+  *
+  * Then the application should submit packets with opus_repacketizer_cat(),
+  * extract new packets with opus_repacketizer_out() or
+  * opus_repacketizer_out_range(), and then reset the state for the next set of
+  * input packets via opus_repacketizer_init().
+  *
+  * For example, to split a sequence of packets into individual frames:
+  * @code
+  * unsigned char *data;
+  * int len;
+  * while (get_next_packet(&data, &len))
+  * {
+  *   unsigned char out[1276];
+  *   opus_int32 out_len;
+  *   int nb_frames;
+  *   int err;
+  *   int i;
+  *   err = opus_repacketizer_cat(rp, data, len);
+  *   if (err != OPUS_OK)
+  *   {
+  *     release_packet(data);
+  *     return err;
+  *   }
+  *   nb_frames = opus_repacketizer_get_nb_frames(rp);
+  *   for (i = 0; i < nb_frames; i++)
+  *   {
+  *     out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
+  *     if (out_len < 0)
+  *     {
+  *        release_packet(data);
+  *        return (int)out_len;
+  *     }
+  *     output_next_packet(out, out_len);
+  *   }
+  *   opus_repacketizer_init(rp);
+  *   release_packet(data);
+  * }
+  * @endcode
+  *
+  * Alternatively, to combine a sequence of frames into packets that each
+  * contain up to <code>TARGET_DURATION_MS</code> milliseconds of data:
+  * @code
+  * // The maximum number of packets with duration TARGET_DURATION_MS occurs
+  * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
+  * // packets.
+  * unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
+  * opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
+  * int nb_packets;
+  * unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
+  * opus_int32 out_len;
+  * int prev_toc;
+  * nb_packets = 0;
+  * while (get_next_packet(data+nb_packets, len+nb_packets))
+  * {
+  *   int nb_frames;
+  *   int err;
+  *   nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
+  *   if (nb_frames < 1)
+  *   {
+  *     release_packets(data, nb_packets+1);
+  *     return nb_frames;
+  *   }
+  *   nb_frames += opus_repacketizer_get_nb_frames(rp);
+  *   // If adding the next packet would exceed our target, or it has an
+  *   // incompatible TOC sequence, output the packets we already have before
+  *   // submitting it.
+  *   // N.B., The nb_packets > 0 check ensures we've submitted at least one
+  *   // packet since the last call to opus_repacketizer_init(). Otherwise a
+  *   // single packet longer than TARGET_DURATION_MS would cause us to try to
+  *   // output an (invalid) empty packet. It also ensures that prev_toc has
+  *   // been set to a valid value. Additionally, len[nb_packets] > 0 is
+  *   // guaranteed by the call to opus_packet_get_nb_frames() above, so the
+  *   // reference to data[nb_packets][0] should be valid.
+  *   if (nb_packets > 0 && (
+  *       ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
+  *       opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
+  *       TARGET_DURATION_MS*48))
+  *   {
+  *     out_len = opus_repacketizer_out(rp, out, sizeof(out));
+  *     if (out_len < 0)
+  *     {
+  *        release_packets(data, nb_packets+1);
+  *        return (int)out_len;
+  *     }
+  *     output_next_packet(out, out_len);
+  *     opus_repacketizer_init(rp);
+  *     release_packets(data, nb_packets);
+  *     data[0] = data[nb_packets];
+  *     len[0] = len[nb_packets];
+  *     nb_packets = 0;
+  *   }
+  *   err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
+  *   if (err != OPUS_OK)
+  *   {
+  *     release_packets(data, nb_packets+1);
+  *     return err;
+  *   }
+  *   prev_toc = data[nb_packets][0];
+  *   nb_packets++;
+  * }
+  * // Output the final, partial packet.
+  * if (nb_packets > 0)
+  * {
+  *   out_len = opus_repacketizer_out(rp, out, sizeof(out));
+  *   release_packets(data, nb_packets);
+  *   if (out_len < 0)
+  *     return (int)out_len;
+  *   output_next_packet(out, out_len);
+  * }
+  * @endcode
+  *
+  * An alternate way of merging packets is to simply call opus_repacketizer_cat()
+  * unconditionally until it fails. At that point, the merged packet can be
+  * obtained with opus_repacketizer_out() and the input packet for which
+  * opus_repacketizer_cat() needs to be re-added to a newly reinitialized
+  * repacketizer state.
+  */
+
+typedef struct OpusRepacketizer OpusRepacketizer;
+
+/** Gets the size of an <code>OpusRepacketizer</code> structure.
+  * @returns The size in bytes.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
+
+/** (Re)initializes a previously allocated repacketizer state.
+  * The state must be at least the size returned by opus_repacketizer_get_size().
+  * This can be used for applications which use their own allocator instead of
+  * malloc().
+  * It must also be called to reset the queue of packets waiting to be
+  * repacketized, which is necessary if the maximum packet duration of 120 ms
+  * is reached or if you wish to submit packets with a different Opus
+  * configuration (coding mode, audio bandwidth, frame size, or channel count).
+  * Failure to do so will prevent a new packet from being added with
+  * opus_repacketizer_cat().
+  * @see opus_repacketizer_create
+  * @see opus_repacketizer_get_size
+  * @see opus_repacketizer_cat
+  * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to
+  *                                       (re)initialize.
+  * @returns A pointer to the same repacketizer state that was passed in.
+  */
+OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Allocates memory and initializes the new repacketizer with
+ * opus_repacketizer_init().
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
+
+/** Frees an <code>OpusRepacketizer</code> allocated by
+  * opus_repacketizer_create().
+  * @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed.
+  */
+OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
+
+/** Add a packet to the current repacketizer state.
+  * This packet must match the configuration of any packets already submitted
+  * for repacketization since the last call to opus_repacketizer_init().
+  * This means that it must have the same coding mode, audio bandwidth, frame
+  * size, and channel count.
+  * This can be checked in advance by examining the top 6 bits of the first
+  * byte of the packet, and ensuring they match the top 6 bits of the first
+  * byte of any previously submitted packet.
+  * The total duration of audio in the repacketizer state also must not exceed
+  * 120 ms, the maximum duration of a single packet, after adding this packet.
+  *
+  * The contents of the current repacketizer state can be extracted into new
+  * packets using opus_repacketizer_out() or opus_repacketizer_out_range().
+  *
+  * In order to add a packet with a different configuration or to add more
+  * audio beyond 120 ms, you must clear the repacketizer state by calling
+  * opus_repacketizer_init().
+  * If a packet is too large to add to the current repacketizer state, no part
+  * of it is added, even if it contains multiple frames, some of which might
+  * fit.
+  * If you wish to be able to add parts of such packets, you should first use
+  * another repacketizer to split the packet into pieces and add them
+  * individually.
+  * @see opus_repacketizer_out_range
+  * @see opus_repacketizer_out
+  * @see opus_repacketizer_init
+  * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to
+  *                                       add the packet.
+  * @param[in] data <tt>const unsigned char*</tt>: The packet data.
+  *                                                The application must ensure
+  *                                                this pointer remains valid
+  *                                                until the next call to
+  *                                                opus_repacketizer_init() or
+  *                                                opus_repacketizer_destroy().
+  * @param len <tt>opus_int32</tt>: The number of bytes in the packet data.
+  * @returns An error code indicating whether or not the operation succeeded.
+  * @retval #OPUS_OK The packet's contents have been added to the repacketizer
+  *                  state.
+  * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
+  *                              the packet's TOC sequence was not compatible
+  *                              with previously submitted packets (because
+  *                              the coding mode, audio bandwidth, frame size,
+  *                              or channel count did not match), or adding
+  *                              this packet would increase the total amount of
+  *                              audio stored in the repacketizer state to more
+  *                              than 120 ms.
+  */
+OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+
+/** Construct a new packet from data previously submitted to the repacketizer
+  * state via opus_repacketizer_cat().
+  * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
+  *                                       construct the new packet.
+  * @param begin <tt>int</tt>: The index of the first frame in the current
+  *                            repacketizer state to include in the output.
+  * @param end <tt>int</tt>: One past the index of the last frame in the
+  *                          current repacketizer state to include in the
+  *                          output.
+  * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
+  *                                                 store the output packet.
+  * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
+  *                                    the output buffer. In order to guarantee
+  *                                    success, this should be at least
+  *                                    <code>1276</code> for a single frame,
+  *                                    or for multiple frames,
+  *                                    <code>1277*(end-begin)</code>.
+  *                                    However, <code>1*(end-begin)</code> plus
+  *                                    the size of all packet data submitted to
+  *                                    the repacketizer since the last call to
+  *                                    opus_repacketizer_init() or
+  *                                    opus_repacketizer_create() is also
+  *                                    sufficient, and possibly much smaller.
+  * @returns The total size of the output packet on success, or an error code
+  *          on failure.
+  * @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of
+  *                       frames (begin < 0, begin >= end, or end >
+  *                       opus_repacketizer_get_nb_frames()).
+  * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+  *                                complete output packet.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Return the total number of frames contained in packet data submitted to
+  * the repacketizer state so far via opus_repacketizer_cat() since the last
+  * call to opus_repacketizer_init() or opus_repacketizer_create().
+  * This defines the valid range of packets that can be extracted with
+  * opus_repacketizer_out_range() or opus_repacketizer_out().
+  * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the
+  *                                       frames.
+  * @returns The total number of frames contained in the packet data submitted
+  *          to the repacketizer state.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Construct a new packet from data previously submitted to the repacketizer
+  * state via opus_repacketizer_cat().
+  * This is a convenience routine that returns all the data submitted so far
+  * in a single packet.
+  * It is equivalent to calling
+  * @code
+  * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
+  *                             data, maxlen)
+  * @endcode
+  * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
+  *                                       construct the new packet.
+  * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
+  *                                                 store the output packet.
+  * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
+  *                                    the output buffer. In order to guarantee
+  *                                    success, this should be at least
+  *                                    <code>1277*opus_repacketizer_get_nb_frames(rp)</code>.
+  *                                    However,
+  *                                    <code>1*opus_repacketizer_get_nb_frames(rp)</code>
+  *                                    plus the size of all packet data
+  *                                    submitted to the repacketizer since the
+  *                                    last call to opus_repacketizer_init() or
+  *                                    opus_repacketizer_create() is also
+  *                                    sufficient, and possibly much smaller.
+  * @returns The total size of the output packet on success, or an error code
+  *          on failure.
+  * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+  *                                complete output packet.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
+
+/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
+  * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+  *                                                   packet to pad.
+  * @param len <tt>opus_int32</tt>: The size of the packet.
+  *                                 This must be at least 1.
+  * @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
+  *                                 This must be at least as large as len.
+  * @returns an error code
+  * @retval #OPUS_OK \a on success.
+  * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+  * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+  */
+OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
+
+/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
+  * minimize space usage.
+  * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+  *                                                   packet to strip.
+  * @param len <tt>opus_int32</tt>: The size of the packet.
+  *                                 This must be at least 1.
+  * @returns The new size of the output packet on success, or an error code
+  *          on failure.
+  * @retval #OPUS_BAD_ARG \a len was less than 1.
+  * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
+
+/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
+  * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+  *                                                   packet to pad.
+  * @param len <tt>opus_int32</tt>: The size of the packet.
+  *                                 This must be at least 1.
+  * @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
+  *                                 This must be at least 1.
+  * @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
+  *                                 This must be at least as large as len.
+  * @returns an error code
+  * @retval #OPUS_OK \a on success.
+  * @retval #OPUS_BAD_ARG \a len was less than 1.
+  * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+  */
+OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
+
+/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
+  * minimize space usage.
+  * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+  *                                                   packet to strip.
+  * @param len <tt>opus_int32</tt>: The size of the packet.
+  *                                 This must be at least 1.
+  * @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
+  *                                 This must be at least 1.
+  * @returns The new size of the output packet on success, or an error code
+  *          on failure.
+  * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+  * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_custom.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_custom.h
new file mode 100644 (file)
index 0000000..128650f
--- /dev/null
@@ -0,0 +1,381 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2008-2012 Gregory Maxwell
+   Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+  @file opus_custom.h
+  @brief Opus-Custom reference implementation API
+ */
+
+#ifndef OPUS_CUSTOM_H
+#define OPUS_CUSTOM_H
+
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
+# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
+#else
+# define OPUS_CUSTOM_EXPORT
+# ifdef OPUS_BUILD
+#  define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
+# else
+#  define OPUS_CUSTOM_EXPORT_STATIC
+# endif
+#endif
+
+/** @defgroup opus_custom Opus Custom
+  * @{
+  *  Opus Custom is an optional part of the Opus specification and
+  * reference implementation which uses a distinct API from the regular
+  * API and supports frame sizes that are not normally supported.\ Use
+  * of Opus Custom is discouraged for all but very special applications
+  * for which a frame size different from 2.5, 5, 10, or 20 ms is needed
+  * (for either complexity or latency reasons) and where interoperability
+  * is less important.
+  *
+  * In addition to the interoperability limitations the use of Opus custom
+  * disables a substantial chunk of the codec and generally lowers the
+  * quality available at a given bitrate. Normally when an application needs
+  * a different frame size from the codec it should buffer to match the
+  * sizes but this adds a small amount of delay which may be important
+  * in some very low latency applications. Some transports (especially
+  * constant rate RF transports) may also work best with frames of
+  * particular durations.
+  *
+  * Libopus only supports custom modes if they are enabled at compile time.
+  *
+  * The Opus Custom API is similar to the regular API but the
+  * @ref opus_encoder_create and @ref opus_decoder_create calls take
+  * an additional mode parameter which is a structure produced by
+  * a call to @ref opus_custom_mode_create. Both the encoder and decoder
+  * must create a mode using the same sample rate (fs) and frame size
+  * (frame size) so these parameters must either be signaled out of band
+  * or fixed in a particular implementation.
+  *
+  * Similar to regular Opus the custom modes support on the fly frame size
+  * switching, but the sizes available depend on the particular frame size in
+  * use. For some initial frame sizes on a single on the fly size is available.
+  */
+
+/** Contains the state of an encoder. One encoder state is needed
+    for each stream. It is initialized once at the beginning of the
+    stream. Do *not* re-initialize the state for every frame.
+   @brief Encoder state
+ */
+typedef struct OpusCustomEncoder OpusCustomEncoder;
+
+/** State of the decoder. One decoder state is needed for each stream.
+    It is initialized once at the beginning of the stream. Do *not*
+    re-initialize the state for every frame.
+   @brief Decoder state
+ */
+typedef struct OpusCustomDecoder OpusCustomDecoder;
+
+/** The mode contains all the information necessary to create an
+    encoder. Both the encoder and decoder need to be initialized
+    with exactly the same mode, otherwise the output will be
+    corrupted. The mode MUST NOT BE DESTROYED until the encoders and
+    decoders that use it are destroyed as well.
+   @brief Mode configuration
+ */
+typedef struct OpusCustomMode OpusCustomMode;
+
+/** Creates a new mode struct. This will be passed to an encoder or
+  * decoder. The mode MUST NOT BE DESTROYED until the encoders and
+  * decoders that use it are destroyed as well.
+  * @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
+  * @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
+  *        packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
+  * @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
+  * @return A newly created mode
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
+
+/** Destroys a mode struct. Only call this after all encoders and
+  * decoders using this mode are destroyed as well.
+  * @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
+  */
+OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
+
+/* Encoder */
+/** Gets the size of an OpusCustomEncoder structure.
+  * @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @returns size
+  */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
+    const OpusCustomMode *mode,
+    int channels
+) OPUS_ARG_NONNULL(1);
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+/** Initializes a previously allocated encoder state
+  * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
+  * This is intended for applications which use their own allocator instead of malloc.
+  * @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
+  * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+  * @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
+  *  the stream (must be the same characteristics as used for the
+  *  decoder)
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @return OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
+    OpusCustomEncoder *st,
+    const OpusCustomMode *mode,
+    int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+# endif
+#endif
+
+
+/** Creates a new encoder state. Each stream needs its own encoder
+  * state (can't be shared across simultaneous streams).
+  * @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
+  *  the stream (must be the same characteristics as used for the
+  *  decoder)
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @param [out] error <tt>int*</tt>: Returns an error code
+  * @return Newly created encoder state.
+*/
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
+    const OpusCustomMode *mode,
+    int channels,
+    int *error
+) OPUS_ARG_NONNULL(1);
+
+
+/** Destroys an encoder state.
+  * @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
+  */
+OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
+
+/** Encodes a frame of audio.
+  * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
+  *          Samples with a range beyond +/-1.0 are supported but will
+  *          be clipped by decoders using the integer API and should
+  *          only be used if it is known that the far end supports
+  *          extended dynamic range. There must be exactly
+  *          frame_size samples per channel.
+  * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+  * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+  * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+  *          (can change from one frame to another)
+  * @return Number of bytes written to "compressed".
+  *       If negative, an error has occurred (see error codes). It is IMPORTANT that
+  *       the length returned be somehow transmitted to the decoder. Otherwise, no
+  *       decoding is possible.
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
+    OpusCustomEncoder *st,
+    const float *pcm,
+    int frame_size,
+    unsigned char *compressed,
+    int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a frame of audio.
+  * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
+  *          There must be exactly frame_size samples per channel.
+  * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+  * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+  * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+  *          (can change from one frame to another)
+  * @return Number of bytes written to "compressed".
+  *       If negative, an error has occurred (see error codes). It is IMPORTANT that
+  *       the length returned be somehow transmitted to the decoder. Otherwise, no
+  *       decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
+    OpusCustomEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *compressed,
+    int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a frame of audio.
+  * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int32*</tt>: PCM audio in signed 32-bit format (native endian) representing (or slightly exceeding) 24-bit values.
+  *          There must be exactly frame_size samples per channel.
+  * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+  * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+  * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+  *          (can change from one frame to another)
+  * @return Number of bytes written to "compressed".
+  *       If negative, an error has occurred (see error codes). It is IMPORTANT that
+  *       the length returned be somehow transmitted to the decoder. Otherwise, no
+  *       decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode24(
+    OpusCustomEncoder *st,
+    const opus_int32 *pcm,
+    int frame_size,
+    unsigned char *compressed,
+    int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom encoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @see opus_encoderctls
+  */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
+/* Decoder */
+
+/** Gets the size of an OpusCustomDecoder structure.
+  * @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @returns size
+  */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
+    const OpusCustomMode *mode,
+    int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Initializes a previously allocated decoder state
+  * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
+  * This is intended for applications which use their own allocator instead of malloc.
+  * @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
+  * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+  * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+  * @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
+  *  the stream (must be the same characteristics as used for the
+  *  encoder)
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @return OPUS_OK Success or @ref opus_errorcodes
+  */
+OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
+    OpusCustomDecoder *st,
+    const OpusCustomMode *mode,
+    int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+#endif
+
+
+/** Creates a new decoder state. Each stream needs its own decoder state (can't
+  * be shared across simultaneous streams).
+  * @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
+  *          stream (must be the same characteristics as used for the encoder)
+  * @param [in] channels <tt>int</tt>: Number of channels
+  * @param [out] error <tt>int*</tt>: Returns an error code
+  * @return Newly created decoder state.
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
+    const OpusCustomMode *mode,
+    int channels,
+    int *error
+) OPUS_ARG_NONNULL(1);
+
+/** Destroys a decoder state.
+  * @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
+  */
+OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
+
+/** Decode an opus custom frame with floating point output
+  * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>int</tt>: Number of bytes in payload
+  * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(float)
+  * @param [in] frame_size Number of samples per channel of available space in *pcm.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
+    OpusCustomDecoder *st,
+    const unsigned char *data,
+    int len,
+    float *pcm,
+    int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an opus custom frame
+  * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>int</tt>: Number of bytes in payload
+  * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel of available space in *pcm.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
+    OpusCustomDecoder *st,
+    const unsigned char *data,
+    int len,
+    opus_int16 *pcm,
+    int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an opus custom frame
+  * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>int</tt>: Number of bytes in payload
+  * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
+  *  is frame_size*channels*sizeof(opus_int32)
+  * @param [in] frame_size Number of samples per channel of available space in *pcm.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode24(
+    OpusCustomDecoder *st,
+    const unsigned char *data,
+    int len,
+    opus_int32 *pcm,
+    int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom decoder.
+  *
+  * Generally the request and subsequent arguments are generated
+  * by a convenience macro.
+  * @see opus_genericctls
+  */
+OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_CUSTOM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_defines.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_defines.h
new file mode 100644 (file)
index 0000000..4a61406
--- /dev/null
@@ -0,0 +1,867 @@
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_defines.h
+ * @brief Opus reference implementation constants
+ */
+
+#ifndef OPUS_DEFINES_H
+#define OPUS_DEFINES_H
+
+#include "opus_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup opus_errorcodes Error codes
+ * @{
+ */
+/** No error @hideinitializer*/
+#define OPUS_OK                0
+/** One or more invalid/out of range arguments @hideinitializer*/
+#define OPUS_BAD_ARG          -1
+/** Not enough bytes allocated in the buffer @hideinitializer*/
+#define OPUS_BUFFER_TOO_SMALL -2
+/** An internal error was detected @hideinitializer*/
+#define OPUS_INTERNAL_ERROR   -3
+/** The compressed data passed is corrupted @hideinitializer*/
+#define OPUS_INVALID_PACKET   -4
+/** Invalid/unsupported request number @hideinitializer*/
+#define OPUS_UNIMPLEMENTED    -5
+/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
+#define OPUS_INVALID_STATE    -6
+/** Memory allocation has failed @hideinitializer*/
+#define OPUS_ALLOC_FAIL       -7
+/**@}*/
+
+/** @cond OPUS_INTERNAL_DOC */
+/**Export control for opus functions */
+
+#ifndef OPUS_EXPORT
+# if defined(_WIN32)
+#  if defined(OPUS_BUILD) && defined(DLL_EXPORT)
+#   define OPUS_EXPORT __declspec(dllexport)
+#  else
+#   define OPUS_EXPORT
+#  endif
+# elif defined(__GNUC__) && defined(OPUS_BUILD)
+#  define OPUS_EXPORT __attribute__ ((visibility ("default")))
+# else
+#  define OPUS_EXPORT
+# endif
+#endif
+
+# if !defined(OPUS_GNUC_PREREQ)
+#  if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+#   define OPUS_GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+#  else
+#   define OPUS_GNUC_PREREQ(_maj,_min) 0
+#  endif
+# endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(3,0)
+#  define OPUS_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+#  define OPUS_RESTRICT __restrict
+# else
+#  define OPUS_RESTRICT
+# endif
+#else
+# define OPUS_RESTRICT restrict
+#endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(2,7)
+#  define OPUS_INLINE __inline__
+# elif (defined(_MSC_VER))
+#  define OPUS_INLINE __inline
+# else
+#  define OPUS_INLINE
+# endif
+#else
+# define OPUS_INLINE inline
+#endif
+
+/**Warning attributes for opus functions
+  * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
+  * some paranoid null checks. */
+#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+# define OPUS_WARN_UNUSED_RESULT
+#endif
+#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_ARG_NONNULL(_x)  __attribute__ ((__nonnull__(_x)))
+#else
+# define OPUS_ARG_NONNULL(_x)
+#endif
+
+/** These are the actual Encoder CTL ID numbers.
+  * They should not be used directly by applications.
+  * In general, SETs should be even and GETs should be odd.*/
+#define OPUS_SET_APPLICATION_REQUEST         4000
+#define OPUS_GET_APPLICATION_REQUEST         4001
+#define OPUS_SET_BITRATE_REQUEST             4002
+#define OPUS_GET_BITRATE_REQUEST             4003
+#define OPUS_SET_MAX_BANDWIDTH_REQUEST       4004
+#define OPUS_GET_MAX_BANDWIDTH_REQUEST       4005
+#define OPUS_SET_VBR_REQUEST                 4006
+#define OPUS_GET_VBR_REQUEST                 4007
+#define OPUS_SET_BANDWIDTH_REQUEST           4008
+#define OPUS_GET_BANDWIDTH_REQUEST           4009
+#define OPUS_SET_COMPLEXITY_REQUEST          4010
+#define OPUS_GET_COMPLEXITY_REQUEST          4011
+#define OPUS_SET_INBAND_FEC_REQUEST          4012
+#define OPUS_GET_INBAND_FEC_REQUEST          4013
+#define OPUS_SET_PACKET_LOSS_PERC_REQUEST    4014
+#define OPUS_GET_PACKET_LOSS_PERC_REQUEST    4015
+#define OPUS_SET_DTX_REQUEST                 4016
+#define OPUS_GET_DTX_REQUEST                 4017
+#define OPUS_SET_VBR_CONSTRAINT_REQUEST      4020
+#define OPUS_GET_VBR_CONSTRAINT_REQUEST      4021
+#define OPUS_SET_FORCE_CHANNELS_REQUEST      4022
+#define OPUS_GET_FORCE_CHANNELS_REQUEST      4023
+#define OPUS_SET_SIGNAL_REQUEST              4024
+#define OPUS_GET_SIGNAL_REQUEST              4025
+#define OPUS_GET_LOOKAHEAD_REQUEST           4027
+/* #define OPUS_RESET_STATE 4028 */
+#define OPUS_GET_SAMPLE_RATE_REQUEST         4029
+#define OPUS_GET_FINAL_RANGE_REQUEST         4031
+#define OPUS_GET_PITCH_REQUEST               4033
+#define OPUS_SET_GAIN_REQUEST                4034
+#define OPUS_GET_GAIN_REQUEST                4045 /* Should have been 4035 */
+#define OPUS_SET_LSB_DEPTH_REQUEST           4036
+#define OPUS_GET_LSB_DEPTH_REQUEST           4037
+#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
+#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
+#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
+#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
+#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
+/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
+#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
+#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+#define OPUS_GET_IN_DTX_REQUEST              4049
+#define OPUS_SET_DRED_DURATION_REQUEST 4050
+#define OPUS_GET_DRED_DURATION_REQUEST 4051
+#define OPUS_SET_DNN_BLOB_REQUEST 4052
+/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */
+#define OPUS_SET_OSCE_BWE_REQUEST 4054
+#define OPUS_GET_OSCE_BWE_REQUEST 4055
+#define OPUS_SET_QEXT_REQUEST 4056
+#define OPUS_GET_QEXT_REQUEST 4057
+#define OPUS_SET_IGNORE_EXTENSIONS_REQUEST 4058
+#define OPUS_GET_IGNORE_EXTENSIONS_REQUEST 4059
+
+/** Defines for the presence of extended APIs. */
+#define OPUS_HAVE_OPUS_PROJECTION_H
+
+/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
+#define opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
+
+#ifdef DISABLE_PTR_CHECK
+/* Disable checks to prevent ubsan from complaining about NULL checks
+   in test_opus_api. */
+#define opus_check_int_ptr(ptr) (ptr)
+#define opus_check_uint_ptr(ptr) (ptr)
+#define opus_check_uint8_ptr(ptr) (ptr)
+#define opus_check_val16_ptr(ptr) (ptr)
+#define opus_check_void_ptr(ptr) (ptr)
+#else
+#define opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
+#define opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
+#define opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr)))
+#define opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
+#define opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x))
+#endif
+/** @endcond */
+
+/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
+  * @see opus_genericctls, opus_encoderctls
+  * @{
+  */
+/* Values for the various encoder CTLs */
+#define OPUS_AUTO                           -1000 /**<Auto/default setting @hideinitializer*/
+#define OPUS_BITRATE_MAX                       -1 /**<Maximum bitrate @hideinitializer*/
+
+/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
+ * @hideinitializer */
+#define OPUS_APPLICATION_VOIP                2048
+/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
+ * @hideinitializer */
+#define OPUS_APPLICATION_AUDIO               2049
+/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
+ * @hideinitializer */
+#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
+/** Experts only: forces SILK encoding; don't allocate CELT state at all. Disables OPUS_SET_APPLICATION. */
+#define OPUS_APPLICATION_RESTRICTED_SILK     2052
+/** Experts only: forces CELT encoding; don't allocate SILK state at all. Disables OPUS_SET_APPLICATION. */
+#define OPUS_APPLICATION_RESTRICTED_CELT     2053
+
+#define OPUS_SIGNAL_VOICE                    3001 /**< Signal being encoded is voice */
+#define OPUS_SIGNAL_MUSIC                    3002 /**< Signal being encoded is music */
+#define OPUS_BANDWIDTH_NARROWBAND            1101 /**< 4 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_MEDIUMBAND            1102 /**< 6 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_WIDEBAND              1103 /**< 8 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_SUPERWIDEBAND         1104 /**<12 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_FULLBAND              1105 /**<20 kHz bandpass @hideinitializer*/
+
+#define OPUS_FRAMESIZE_ARG                   5000 /**< Select frame size from the argument (default) */
+#define OPUS_FRAMESIZE_2_5_MS                5001 /**< Use 2.5 ms frames */
+#define OPUS_FRAMESIZE_5_MS                  5002 /**< Use 5 ms frames */
+#define OPUS_FRAMESIZE_10_MS                 5003 /**< Use 10 ms frames */
+#define OPUS_FRAMESIZE_20_MS                 5004 /**< Use 20 ms frames */
+#define OPUS_FRAMESIZE_40_MS                 5005 /**< Use 40 ms frames */
+#define OPUS_FRAMESIZE_60_MS                 5006 /**< Use 60 ms frames */
+#define OPUS_FRAMESIZE_80_MS                 5007 /**< Use 80 ms frames */
+#define OPUS_FRAMESIZE_100_MS                5008 /**< Use 100 ms frames */
+#define OPUS_FRAMESIZE_120_MS                5009 /**< Use 120 ms frames */
+
+/**@}*/
+
+
+/** @defgroup opus_encoderctls Encoder related CTLs
+  *
+  * These are convenience macros for use with the \c opus_encode_ctl
+  * interface. They are used to generate the appropriate series of
+  * arguments for that call, passing the correct type, size and so
+  * on as expected for each particular request.
+  *
+  * Some usage examples:
+  *
+  * @code
+  * int ret;
+  * ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
+  * if (ret != OPUS_OK) return ret;
+  *
+  * opus_int32 rate;
+  * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
+  *
+  * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+  * @endcode
+  *
+  * @see opus_genericctls, opus_encoder
+  * @{
+  */
+
+/** Configures the encoder's computational complexity.
+  * The supported range is 0-10 inclusive with 10 representing the highest complexity.
+  * @see OPUS_GET_COMPLEXITY
+  * @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
+  *
+  * @hideinitializer */
+#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, opus_check_int(x)
+/** Gets the encoder's complexity configuration.
+  * @see OPUS_SET_COMPLEXITY
+  * @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
+  *                                      inclusive.
+  * @hideinitializer */
+#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the bitrate in the encoder.
+  * Rates from 500 to 512000 bits per second are meaningful, as well as the
+  * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
+  * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
+  * rate as it can, which is useful for controlling the rate by adjusting the
+  * output buffer size.
+  * @see OPUS_GET_BITRATE
+  * @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
+  *                                   is determined based on the number of
+  *                                   channels and the input sampling rate.
+  * @hideinitializer */
+#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, opus_check_int(x)
+/** Gets the encoder's bitrate configuration.
+  * @see OPUS_SET_BITRATE
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
+  *                                      The default is determined based on the
+  *                                      number of channels and the input
+  *                                      sampling rate.
+  * @hideinitializer */
+#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, opus_check_int_ptr(x)
+
+/** Enables or disables variable bitrate (VBR) in the encoder.
+  * The configured bitrate may not be met exactly because frames must
+  * be an integer number of bytes in length.
+  * @see OPUS_GET_VBR
+  * @see OPUS_SET_VBR_CONSTRAINT
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
+  *               cause noticeable quality degradation.</dd>
+  * <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
+  *               #OPUS_SET_VBR_CONSTRAINT.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, opus_check_int(x)
+/** Determine if variable bitrate (VBR) is enabled in the encoder.
+  * @see OPUS_SET_VBR
+  * @see OPUS_GET_VBR_CONSTRAINT
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Hard CBR.</dd>
+  * <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
+  *               #OPUS_GET_VBR_CONSTRAINT.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, opus_check_int_ptr(x)
+
+/** Enables or disables constrained VBR in the encoder.
+  * This setting is ignored when the encoder is in CBR mode.
+  * @warning Only the MDCT mode of Opus currently heeds the constraint.
+  *  Speech mode ignores it completely, hybrid mode may fail to obey it
+  *  if the LPC layer uses more bitrate than the constraint would have
+  *  permitted.
+  * @see OPUS_GET_VBR_CONSTRAINT
+  * @see OPUS_SET_VBR
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Unconstrained VBR.</dd>
+  * <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
+  *               frame of buffering delay assuming a transport with a
+  *               serialization speed of the nominal bitrate.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, opus_check_int(x)
+/** Determine if constrained VBR is enabled in the encoder.
+  * @see OPUS_SET_VBR_CONSTRAINT
+  * @see OPUS_GET_VBR
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Unconstrained VBR.</dd>
+  * <dt>1</dt><dd>Constrained VBR (default).</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, opus_check_int_ptr(x)
+
+/** Configures mono/stereo forcing in the encoder.
+  * This can force the encoder to produce packets encoded as either mono or
+  * stereo, regardless of the format of the input audio. This is useful when
+  * the caller knows that the input signal is currently a mono source embedded
+  * in a stereo stream.
+  * @see OPUS_GET_FORCE_CHANNELS
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+  * <dt>1</dt>         <dd>Forced mono</dd>
+  * <dt>2</dt>         <dd>Forced stereo</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, opus_check_int(x)
+/** Gets the encoder's forced channel configuration.
+  * @see OPUS_SET_FORCE_CHANNELS
+  * @param[out] x <tt>opus_int32 *</tt>:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+  * <dt>1</dt>         <dd>Forced mono</dd>
+  * <dt>2</dt>         <dd>Forced stereo</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the maximum bandpass that the encoder will select automatically.
+  * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
+  * (leaving that set to the default, #OPUS_AUTO). This allows the
+  * application to set an upper bound based on the type of input it is
+  * providing, but still gives the encoder the freedom to reduce the bandpass
+  * when the bitrate becomes too low, for better overall quality.
+  * @see OPUS_GET_MAX_BANDWIDTH
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband (default)</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, opus_check_int(x)
+
+/** Gets the encoder's configured maximum allowed bandpass.
+  * @see OPUS_SET_MAX_BANDWIDTH
+  * @param[out] x <tt>opus_int32 *</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband (default)</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, opus_check_int_ptr(x)
+
+/** Sets the encoder's bandpass to a specific value.
+  * This prevents the encoder from automatically selecting the bandpass based
+  * on the available bitrate. If an application knows the bandpass of the input
+  * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
+  * instead, which still gives the encoder the freedom to reduce the bandpass
+  * when the bitrate becomes too low, for better overall quality.
+  * @see OPUS_GET_BANDWIDTH
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>                    <dd>(default)</dd>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, opus_check_int(x)
+
+/** Configures the type of signal being encoded.
+  * This is a hint which helps the encoder's mode selection.
+  * @see OPUS_GET_SIGNAL
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>        <dd>(default)</dd>
+  * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+  * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured signal type.
+  * @see OPUS_SET_SIGNAL
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>        <dd>(default)</dd>
+  * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+  * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, opus_check_int_ptr(x)
+
+
+/** Configures the encoder's intended application.
+  * The initial value is a mandatory argument to the encoder_create function.
+  * @see OPUS_GET_APPLICATION
+  * @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured application.
+  * @see OPUS_SET_APPLICATION
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the total samples of delay added by the entire codec.
+  * This can be queried by the encoder and then the provided number of samples can be
+  * skipped on from the start of the decoder's output to provide time aligned input
+  * and output. From the perspective of a decoding application the real data begins this many
+  * samples late.
+  *
+  * The decoder contribution to this delay is identical for all decoders, but the
+  * encoder portion of the delay may vary from implementation to implementation,
+  * version to version, or even depend on the encoder's initial configuration.
+  * Applications needing delay compensation should call this CTL rather than
+  * hard-coding a value.
+  * @param[out] x <tt>opus_int32 *</tt>:   Number of lookahead samples
+  * @hideinitializer */
+#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of inband forward error correction (FEC).
+  * @note This is only applicable to the LPC layer
+  * @see OPUS_GET_INBAND_FEC
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Disable inband FEC (default).</dd>
+  * <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
+  * <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, opus_check_int(x)
+/** Gets encoder's configured use of inband forward error correction.
+  * @see OPUS_SET_INBAND_FEC
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Inband FEC disabled (default).</dd>
+  * <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
+  * <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's expected packet loss percentage.
+  * Higher values trigger progressively more loss resistant behavior in the encoder
+  * at the expense of quality at a given bitrate in the absence of packet loss, but
+  * greater quality under loss.
+  * @see OPUS_GET_PACKET_LOSS_PERC
+  * @param[in] x <tt>opus_int32</tt>:   Loss percentage in the range 0-100, inclusive (default: 0).
+  * @hideinitializer */
+#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured packet loss percentage.
+  * @see OPUS_SET_PACKET_LOSS_PERC
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
+  *                                      in the range 0-100, inclusive (default: 0).
+  * @hideinitializer */
+#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of discontinuous transmission (DTX).
+  * @note This is only applicable to the LPC layer
+  * @see OPUS_GET_DTX
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Disable DTX (default).</dd>
+  * <dt>1</dt><dd>Enabled DTX.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, opus_check_int(x)
+/** Gets encoder's configured use of discontinuous transmission.
+  * @see OPUS_SET_DTX
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>DTX disabled (default).</dd>
+  * <dt>1</dt><dd>DTX enabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, opus_check_int_ptr(x)
+/** Configures the depth of signal being encoded.
+  *
+  * This is a hint which helps the encoder identify silence and near-silence.
+  * It represents the number of significant bits of linear intensity below
+  * which the signal contains ignorable quantization or other noise.
+  *
+  * For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
+  * for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
+  * for 16-bit linear pcm input with opus_encode_float().
+  *
+  * When using opus_encode() instead of opus_encode_float(), or when libopus
+  * is compiled for fixed-point, the encoder uses the minimum of the value
+  * set here and the value 16.
+  *
+  * @see OPUS_GET_LSB_DEPTH
+  * @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
+  *                                   (default: 24).
+  * @hideinitializer */
+#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured signal depth.
+  * @see OPUS_SET_LSB_DEPTH
+  * @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
+  *                                      24 (default: 24).
+  * @hideinitializer */
+#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of variable duration frames.
+  * When variable duration is enabled, the encoder is free to use a shorter frame
+  * size than the one requested in the opus_encode*() call.
+  * It is then the user's responsibility
+  * to verify how much audio was encoded by checking the ToC byte of the encoded
+  * packet. The part of the audio that was not encoded needs to be resent to the
+  * encoder for the next call. Do not use this option unless you <b>really</b>
+  * know what you are doing.
+  * @see OPUS_GET_EXPERT_FRAME_DURATION
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+  * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured use of variable duration frames.
+  * @see OPUS_SET_EXPERT_FRAME_DURATION
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+  * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, disables almost all use of prediction, making frames almost
+  * completely independent. This reduces quality.
+  * @see OPUS_GET_PREDICTION_DISABLED
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Enable prediction (default).</dd>
+  * <dt>1</dt><dd>Disable prediction.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured prediction status.
+  * @see OPUS_SET_PREDICTION_DISABLED
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Prediction enabled (default).</dd>
+  * <dt>1</dt><dd>Prediction disabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, opus_check_int_ptr(x)
+
+/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
+  * @hideinitializer */
+#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
+  * @hideinitializer */
+#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** Provide external DNN weights from binary object (only when explicitly built without the weights)
+  * @hideinitializer */
+#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, opus_check_void_ptr(data), opus_check_int(len)
+
+/** If set to 1, enables quality extension (QEXT), otherwise disables it (default). Warning: This will *hurt* audio quality unless operating at
+    a very high bitrate.
+  * @hideinitializer */
+#define OPUS_SET_QEXT(x) OPUS_SET_QEXT_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured quality extension (QEXT).
+  * @hideinitializer */
+#define OPUS_GET_QEXT(x) OPUS_GET_QEXT_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_genericctls Generic CTLs
+  *
+  * These macros are used with the \c opus_decoder_ctl and
+  * \c opus_encoder_ctl calls to generate a particular
+  * request.
+  *
+  * When called on an \c OpusDecoder they apply to that
+  * particular decoder instance. When called on an
+  * \c OpusEncoder they apply to the corresponding setting
+  * on that encoder instance, if present.
+  *
+  * Some usage examples:
+  *
+  * @code
+  * int ret;
+  * opus_int32 pitch;
+  * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
+  * if (ret == OPUS_OK) return ret;
+  *
+  * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+  * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
+  *
+  * opus_int32 enc_bw, dec_bw;
+  * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
+  * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
+  * if (enc_bw != dec_bw) {
+  *   printf("packet bandwidth mismatch!\n");
+  * }
+  * @endcode
+  *
+  * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
+  * @{
+  */
+
+/** Resets the codec state to be equivalent to a freshly initialized state.
+  * This should be called when switching streams in order to prevent
+  * the back to back decoding from giving different results from
+  * one at a time decoding.
+  * @hideinitializer */
+#define OPUS_RESET_STATE 4028
+
+/** Gets the final state of the codec's entropy coder.
+  * This is used for testing purposes,
+  * The encoder and decoder state should be identical after coding a payload
+  * (assuming no data corruption or software bugs)
+  *
+  * @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
+  *
+  * @hideinitializer */
+#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, opus_check_uint_ptr(x)
+
+/** Gets the encoder's configured bandpass or the decoder's last bandpass.
+  * @see OPUS_SET_BANDWIDTH
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>#OPUS_AUTO</dt>                    <dd>(default)</dd>
+  * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt>    <dd>4 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt>    <dd>6 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt>      <dd>8 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+  * <dt>#OPUS_BANDWIDTH_FULLBAND</dt>     <dd>20 kHz passband</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the sampling rate the encoder or decoder was initialized with.
+  * This simply returns the <code>Fs</code> value passed to opus_encoder_init()
+  * or opus_decoder_init().
+  * @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
+  * @hideinitializer
+  */
+#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, disables the use of phase inversion for intensity stereo,
+  * improving the quality of mono downmixes, but slightly reducing normal
+  * stereo quality. Disabling phase inversion in the decoder does not comply
+  * with RFC 6716, although it does not cause any interoperability issue and
+  * is expected to become part of the Opus standard once RFC 6716 is updated
+  * by draft-ietf-codec-opus-update.
+  * @see OPUS_GET_PHASE_INVERSION_DISABLED
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Enable phase inversion (default).</dd>
+  * <dt>1</dt><dd>Disable phase inversion.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured phase inversion status.
+  * @see OPUS_SET_PHASE_INVERSION_DISABLED
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
+  * <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int_ptr(x)
+/** Gets the DTX state of the encoder.
+  * Returns whether the last encoded frame was either a comfort noise update
+  * during DTX or not encoded because of DTX.
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>The encoder is not in DTX.</dd>
+  * <dt>1</dt><dd>The encoder is in DTX.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_decoderctls Decoder related CTLs
+  * @see opus_genericctls, opus_encoderctls, opus_decoder
+  * @{
+  */
+
+/** Configures decoder gain adjustment.
+  * Scales the decoded output by a factor specified in Q8 dB units.
+  * This has a maximum range of -32768 to 32767 inclusive, and returns
+  * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
+  * This setting survives decoder reset.
+  *
+  * gain = pow(10, x/(20.0*256))
+  *
+  * @param[in] x <tt>opus_int32</tt>:   Amount to scale PCM signal by in Q8 dB units.
+  * @hideinitializer */
+#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, opus_check_int(x)
+/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
+  *
+  * @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
+  * @hideinitializer */
+#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
+  * @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
+  * @hideinitializer */
+#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the pitch of the last decoded frame, if available.
+  * This can be used for any post-processing algorithm requiring the use of pitch,
+  * e.g. time stretching/shortening. If the last frame was not voiced, or if the
+  * pitch was not coded in the frame, then zero is returned.
+  *
+  * This CTL is only implemented for decoder instances.
+  *
+  * @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
+  *
+  * @hideinitializer */
+#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, opus_check_int_ptr(x)
+
+/** Enables blind bandwidth extension for wideband signals if decoding sampling rate is 48 kHz.
+  * @param[in] x <tt>opus_int32 </tt>: 1 enables bandwidth extension, 0 disables it.
+  * The default is 0.
+  *
+  * @hideinitializer */
+ #define OPUS_SET_OSCE_BWE(x) OPUS_SET_OSCE_BWE_REQUEST, opus_check_int(x)
+/** Gets blind bandwidth extension flag for wideband signals if decoding sampling rate is 48 kHz.
+  * @param[out] x <tt>opus_int32 *</tt>: 1 if bwe enabled, 0 if disabled.
+  *
+  * @hideinitializer */
+ #define OPUS_GET_OSCE_BWE(x) OPUS_GET_OSCE_BWE_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, the decoder will ignore all extensions found in the padding area
+  * (does not affect DRED, which is decoded separately).
+  * @hideinitializer */
+#define OPUS_SET_IGNORE_EXTENSIONS(x) OPUS_SET_IGNORE_EXTENSIONS_REQUEST, opus_check_int(x)
+/** Gets whether the decoder is ignoring extensions.
+  * @hideinitializer */
+#define OPUS_GET_IGNORE_EXTENSIONS(x) OPUS_GET_IGNORE_EXTENSIONS_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_libinfo Opus library information functions
+  * @{
+  */
+
+/** Converts an opus error code into a human readable string.
+  *
+  * @param[in] error <tt>int</tt>: Error number
+  * @returns Error string
+  */
+OPUS_EXPORT const char *opus_strerror(int error);
+
+/** Gets the libopus version string.
+  *
+  * Applications may look for the substring "-fixed" in the version string to
+  * determine whether they have a fixed-point or floating-point build at
+  * runtime.
+  *
+  * @returns Version string
+  */
+OPUS_EXPORT const char *opus_get_version_string(void);
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_DEFINES_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_frame_to_pcm.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_frame_to_pcm.h
new file mode 100644 (file)
index 0000000..ea2c790
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef OPUS_FRAME_TO_PCM_H
+#define OPUS_FRAME_TO_PCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Decode a single Opus packet (in-memory) into 16-bit PCM samples.
+ *
+ * @param packet_data      Pointer to Opus packet bytes.
+ * @param packet_len       Length of packet_data in bytes.
+ * @param sample_rate      Sample rate in Hz (e.g. 16000/48000).
+ * @param channels         Channel count. If <= 0, try to detect from packet; fallback 1.
+ * @param out_pcm          Output buffer for interleaved opus_int16 PCM (little-endian in memory).
+ * @param out_pcm_capacity Capacity of out_pcm in samples (not bytes), i.e. max number of opus_int16 entries.
+ * @param out_pcm_samples  [out] Number of samples written to out_pcm (in opus_int16 units, i.e. includes channels).
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int opus_frame_to_pcm_decode_packet(const unsigned char *packet_data, int packet_len,
+                                    int sample_rate, int channels,
+                                    short *out_pcm, int out_pcm_capacity,
+                                    int *out_pcm_samples);
+
+/**
+ * @brief Decode a single Opus packet/frame file into 16-bit little-endian PCM.
+ *
+ * @param input_file  Input file path containing (single) Opus packet bytes.
+ * @param sample_rate Sample rate in Hz (e.g. 16000/48000).
+ * @param channels    Channel count. If <= 0, try to detect from packet; fallback 1.
+ * @param output_file Output PCM file path. If NULL, write to stdout.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int opus_frame_to_pcm_decode_file(const char *input_file, int sample_rate, int channels,
+                                  const char *output_file);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_FRAME_TO_PCM_H */
+
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_multistream.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_multistream.h
new file mode 100644 (file)
index 0000000..81fb2bb
--- /dev/null
@@ -0,0 +1,736 @@
+/* Copyright (c) 2011 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_multistream.h
+ * @brief Opus reference implementation multistream API
+ */
+
+#ifndef OPUS_MULTISTREAM_H
+#define OPUS_MULTISTREAM_H
+
+#include "opus.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** Macros to trigger compilation errors when the wrong types are provided to a
+  * CTL. */
+/**@{*/
+#define opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
+#define opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
+/**@}*/
+
+/** These are the actual encoder and decoder CTL ID numbers.
+  * They should not be used directly by applications.
+  * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
+#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
+/**@}*/
+
+/** @endcond */
+
+/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
+  *
+  * These are convenience macros that are specific to the
+  * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
+  * interface.
+  * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
+  * @ref opus_decoderctls may be applied to a multistream encoder or decoder as
+  * well.
+  * In addition, you may retrieve the encoder or decoder state for an specific
+  * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
+  * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
+  */
+/**@{*/
+
+/** Gets the encoder state for an individual stream of a multistream encoder.
+  * @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
+  *                                   wish to retrieve.
+  *                                   This must be non-negative and less than
+  *                                   the <code>streams</code> parameter used
+  *                                   to initialize the encoder.
+  * @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
+  *                                       encoder state.
+  * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+  * @hideinitializer
+  */
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, opus_check_int(x), opus_check_encstate_ptr(y)
+
+/** Gets the decoder state for an individual stream of a multistream decoder.
+  * @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
+  *                                   wish to retrieve.
+  *                                   This must be non-negative and less than
+  *                                   the <code>streams</code> parameter used
+  *                                   to initialize the decoder.
+  * @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
+  *                                       decoder state.
+  * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+  * @hideinitializer
+  */
+#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, opus_check_int(x), opus_check_decstate_ptr(y)
+
+/**@}*/
+
+/** @defgroup opus_multistream Opus Multistream API
+  * @{
+  *
+  * The multistream API allows individual Opus streams to be combined into a
+  * single packet, enabling support for up to 255 channels. Unlike an
+  * elementary Opus stream, the encoder and decoder must negotiate the channel
+  * configuration before the decoder can successfully interpret the data in the
+  * packets produced by the encoder. Some basic information, such as packet
+  * duration, can be computed without any special negotiation.
+  *
+  * The format for multistream Opus packets is defined in
+  * <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
+  * and is based on the self-delimited Opus framing described in Appendix B of
+  * <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
+  * Normal Opus packets are just a degenerate case of multistream Opus packets,
+  * and can be encoded or decoded with the multistream API by setting
+  * <code>streams</code> to <code>1</code> when initializing the encoder or
+  * decoder.
+  *
+  * Multistream Opus streams can contain up to 255 elementary Opus streams.
+  * These may be either "uncoupled" or "coupled", indicating that the decoder
+  * is configured to decode them to either 1 or 2 channels, respectively.
+  * The streams are ordered so that all coupled streams appear at the
+  * beginning.
+  *
+  * A <code>mapping</code> table defines which decoded channel <code>i</code>
+  * should be used for each input/output (I/O) channel <code>j</code>. This table is
+  * typically provided as an unsigned char array.
+  * Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
+  * If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
+  * encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
+  * is even, or  as the right channel of stream <code>(i/2)</code> if
+  * <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
+  * mono in stream <code>(i - coupled_streams)</code>, unless it has the special
+  * value 255, in which case it is omitted from the encoding entirely (the
+  * decoder will reproduce it as silence). Each value <code>i</code> must either
+  * be the special value 255 or be less than <code>streams + coupled_streams</code>.
+  *
+  * The output channels specified by the encoder
+  * should use the
+  * <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
+  * channel ordering</a>. A decoder may wish to apply an additional permutation
+  * to the mapping the encoder used to achieve a different output channel
+  * order (e.g. for outputting in WAV order).
+  *
+  * Each multistream packet contains an Opus packet for each stream, and all of
+  * the Opus packets in a single multistream packet must have the same
+  * duration. Therefore the duration of a multistream packet can be extracted
+  * from the TOC sequence of the first stream, which is located at the
+  * beginning of the packet, just like an elementary Opus stream:
+  *
+  * @code
+  * int nb_samples;
+  * int nb_frames;
+  * nb_frames = opus_packet_get_nb_frames(data, len);
+  * if (nb_frames < 1)
+  *   return nb_frames;
+  * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
+  * @endcode
+  *
+  * The general encoding and decoding process proceeds exactly the same as in
+  * the normal @ref opus_encoder and @ref opus_decoder APIs.
+  * See their documentation for an overview of how to use the corresponding
+  * multistream functions.
+  */
+
+/** Opus multistream encoder state.
+  * This contains the complete state of a multistream Opus encoder.
+  * It is position independent and can be freely copied.
+  * @see opus_multistream_encoder_create
+  * @see opus_multistream_encoder_init
+  */
+typedef struct OpusMSEncoder OpusMSEncoder;
+
+/** Opus multistream decoder state.
+  * This contains the complete state of a multistream Opus decoder.
+  * It is position independent and can be freely copied.
+  * @see opus_multistream_decoder_create
+  * @see opus_multistream_decoder_init
+  */
+typedef struct OpusMSDecoder OpusMSDecoder;
+
+/**\name Multistream encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusMSEncoder structure.
+  * @param streams <tt>int</tt>: The total number of streams to encode from the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+  *                                      to encode.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      encoded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @returns The size in bytes on success, or a negative error code
+  *          (see @ref opus_errorcodes) on error.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
+      int streams,
+      int coupled_streams
+);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
+      int channels,
+      int mapping_family
+);
+
+
+/** Allocates and initializes a multistream encoder state.
+  * Call opus_multistream_encoder_destroy() to release
+  * this object when finished.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels in the input signal.
+  *                               This must be at most 255.
+  *                               It may be greater than the number of
+  *                               coded channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams to encode from the
+  *                              input.
+  *                              This must be no more than the number of channels.
+  * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+  *                                      to encode.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      encoded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than the number of input channels.
+  * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+  *                    encoded channels to input channels, as described in
+  *                    @ref opus_multistream. As an extra constraint, the
+  *                    multistream encoder does not allow encoding coupled
+  *                    streams for which one channel is unused since this
+  *                    is never a good idea.
+  * @param application <tt>int</tt>: The target encoder application.
+  *                                  This must be one of the following:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+  *                                   code (see @ref opus_errorcodes) on
+  *                                   failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping,
+      int application,
+      int *error
+) OPUS_ARG_NONNULL(5);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
+      opus_int32 Fs,
+      int channels,
+      int mapping_family,
+      int *streams,
+      int *coupled_streams,
+      unsigned char *mapping,
+      int application,
+      int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+/** Initialize a previously allocated multistream encoder state.
+  * The memory pointed to by \a st must be at least the size returned by
+  * opus_multistream_encoder_get_size().
+  * This is intended for applications which use their own allocator instead of
+  * malloc.
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @see opus_multistream_encoder_create
+  * @see opus_multistream_encoder_get_size
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels in the input signal.
+  *                               This must be at most 255.
+  *                               It may be greater than the number of
+  *                               coded channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams to encode from the
+  *                              input.
+  *                              This must be no more than the number of channels.
+  * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+  *                                      to encode.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      encoded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than the number of input channels.
+  * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+  *                    encoded channels to input channels, as described in
+  *                    @ref opus_multistream. As an extra constraint, the
+  *                    multistream encoder does not allow encoding coupled
+  *                    streams for which one channel is unused since this
+  *                    is never a good idea.
+  * @param application <tt>int</tt>: The target encoder application.
+  *                                  This must be one of the following:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+  *          on failure.
+  */
+OPUS_EXPORT int opus_multistream_encoder_init(
+      OpusMSEncoder *st,
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping,
+      int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+OPUS_EXPORT int opus_multistream_surround_encoder_init(
+      OpusMSEncoder *st,
+      opus_int32 Fs,
+      int channels,
+      int mapping_family,
+      int *streams,
+      int *coupled_streams,
+      unsigned char *mapping,
+      int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
+
+/** Encodes a multistream Opus frame.
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+  * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
+  *                                            samples.
+  *                                            This must contain
+  *                                            <code>frame_size*channels</code>
+  *                                            samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
+    OpusMSEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a multistream Opus frame.
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+  * @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
+  *                                            samples representing (or slightly exceeding) 24-bit values.
+  *                                            This must contain
+  *                                            <code>frame_size*channels</code>
+  *                                            samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode24(
+    OpusMSEncoder *st,
+    const opus_int32 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a multistream Opus frame from floating point input.
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+  * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
+  *                                       samples with a normal range of
+  *                                       +/-1.0.
+  *                                       Samples with a range beyond +/-1.0
+  *                                       are supported but will be clipped by
+  *                                       decoders using the integer API and
+  *                                       should only be used if it is known
+  *                                       that the far end supports extended
+  *                                       dynamic range.
+  *                                       This must contain
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
+      OpusMSEncoder *st,
+      const float *pcm,
+      int frame_size,
+      unsigned char *data,
+      opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an <code>OpusMSEncoder</code> allocated by
+  * opus_multistream_encoder_create().
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
+  */
+OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
+
+/** Perform a CTL function on a multistream Opus encoder.
+  *
+  * Generally the request and subsequent arguments are generated by a
+  * convenience macro.
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls,
+  *                @ref opus_encoderctls, or @ref opus_multistream_ctls.
+  * @see opus_genericctls
+  * @see opus_encoderctls
+  * @see opus_multistream_ctls
+  */
+OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+/**\name Multistream decoder functions */
+/**@{*/
+
+/** Gets the size of an <code>OpusMSDecoder</code> structure.
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @returns The size in bytes on success, or a negative error code
+  *          (see @ref opus_errorcodes) on error.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
+      int streams,
+      int coupled_streams
+);
+
+/** Allocates and initializes a multistream decoder state.
+  * Call opus_multistream_decoder_destroy() to release
+  * this object when finished.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels to output.
+  *                               This must be at most 255.
+  *                               It may be different from the number of coded
+  *                               channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+  *                    coded channels to output channels, as described in
+  *                    @ref opus_multistream.
+  * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+  *                                   code (see @ref opus_errorcodes) on
+  *                                   failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping,
+      int *error
+) OPUS_ARG_NONNULL(5);
+
+/** Initialize a previously allocated decoder state object.
+  * The memory pointed to by \a st must be at least the size returned by
+  * opus_multistream_encoder_get_size().
+  * This is intended for applications which use their own allocator instead of
+  * malloc.
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @see opus_multistream_decoder_create
+  * @see opus_multistream_deocder_get_size
+  * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels to output.
+  *                               This must be at most 255.
+  *                               It may be different from the number of coded
+  *                               channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+  *                    coded channels to output channels, as described in
+  *                    @ref opus_multistream.
+  * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+  *          on failure.
+  */
+OPUS_EXPORT int opus_multistream_decoder_init(
+      OpusMSDecoder *st,
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+/** Decode a multistream Opus packet.
+  * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+  *                                       samples.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
+    OpusMSDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int16 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a multistream Opus packet.
+  * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
+  *                                       samples representing (or slightly exceeding) 24-bit values.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode24(
+    OpusMSDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int32 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a multistream Opus packet with floating point output.
+  * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+  *                                       samples.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
+    OpusMSDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    float *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on a multistream Opus decoder.
+  *
+  * Generally the request and subsequent arguments are generated by a
+  * convenience macro.
+  * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls,
+  *                @ref opus_decoderctls, or @ref opus_multistream_ctls.
+  * @see opus_genericctls
+  * @see opus_decoderctls
+  * @see opus_multistream_ctls
+  */
+OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an <code>OpusMSDecoder</code> allocated by
+  * opus_multistream_decoder_create().
+  * @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
+  */
+OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_MULTISTREAM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_projection.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_projection.h
new file mode 100644 (file)
index 0000000..26f3cbb
--- /dev/null
@@ -0,0 +1,643 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_projection.h
+ * @brief Opus projection reference API
+ */
+
+#ifndef OPUS_PROJECTION_H
+#define OPUS_PROJECTION_H
+
+#include "opus_multistream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** These are the actual encoder and decoder CTL ID numbers.
+  * They should not be used directly by applications.c
+  * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST    6001
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST    6003
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST         6005
+/**@}*/
+
+
+/** @endcond */
+
+/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
+  *
+  * These are convenience macros that are specific to the
+  * opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
+  * interface.
+  * The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
+  * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
+  * projection encoder or decoder as well.
+  */
+/**@{*/
+
+/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
+  *                                      of the demixing matrix.
+  * @hideinitializer
+  */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, opus_check_int_ptr(x)
+
+
+/** Gets the size in bytes of the demixing matrix from the encoder.
+  * @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
+  *                                      demixing matrix.
+  * @hideinitializer
+  */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, opus_check_int_ptr(x)
+
+
+/** Copies the demixing matrix to the supplied pointer location.
+  * @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
+  *                                         supplied pointer location.
+  * @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
+  *                              pointer location.
+  * @hideinitializer
+  */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, opus_check_int(y)
+
+
+/**@}*/
+
+/** Opus projection encoder state.
+ * This contains the complete state of a projection Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_ambisonics_encoder_create
+ */
+typedef struct OpusProjectionEncoder OpusProjectionEncoder;
+
+
+/** Opus projection decoder state.
+  * This contains the complete state of a projection Opus decoder.
+  * It is position independent and can be freely copied.
+  * @see opus_projection_decoder_create
+  * @see opus_projection_decoder_init
+  */
+typedef struct OpusProjectionDecoder OpusProjectionDecoder;
+
+
+/**\name Projection encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusProjectionEncoder structure.
+  * @param channels <tt>int</tt>: The total number of input channels to encode.
+  *                               This must be no more than 255.
+  * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+  *                                     the appropriate projection.
+  * @returns The size in bytes on success, or a negative error code
+  *          (see @ref opus_errorcodes) on error.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
+    int channels,
+    int mapping_family
+);
+
+
+/** Allocates and initializes a projection encoder state.
+  * Call opus_projection_encoder_destroy() to release
+  * this object when finished.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels in the input signal.
+  *                               This must be at most 255.
+  *                               It may be greater than the number of
+  *                               coded channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+  *                                     the appropriate projection.
+  * @param[out] streams <tt>int *</tt>: The total number of streams that will
+  *                                     be encoded from the input.
+  * @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
+  *                                 streams that will be encoded from the input.
+  * @param application <tt>int</tt>: The target encoder application.
+  *                                  This must be one of the following:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+  *                                   code (see @ref opus_errorcodes) on
+  *                                   failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
+    opus_int32 Fs,
+    int channels,
+    int mapping_family,
+    int *streams,
+    int *coupled_streams,
+    int application,
+    int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection encoder state.
+  * The memory pointed to by \a st must be at least the size returned by
+  * opus_projection_ambisonics_encoder_get_size().
+  * This is intended for applications which use their own allocator instead of
+  * malloc.
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @see opus_projection_ambisonics_encoder_create
+  * @see opus_projection_ambisonics_encoder_get_size
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels in the input signal.
+  *                               This must be at most 255.
+  *                               It may be greater than the number of
+  *                               coded channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams to encode from the
+  *                              input.
+  *                              This must be no more than the number of channels.
+  * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+  *                                      to encode.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      encoded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than the number of input channels.
+  * @param application <tt>int</tt>: The target encoder application.
+  *                                  This must be one of the following:
+  * <dl>
+  * <dt>#OPUS_APPLICATION_VOIP</dt>
+  * <dd>Process signal for improved speech intelligibility.</dd>
+  * <dt>#OPUS_APPLICATION_AUDIO</dt>
+  * <dd>Favor faithfulness to the original input.</dd>
+  * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+  * <dd>Configure the minimum possible coding delay by disabling certain modes
+  * of operation.</dd>
+  * </dl>
+  * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+  *          on failure.
+  */
+OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
+    OpusProjectionEncoder *st,
+    opus_int32 Fs,
+    int channels,
+    int mapping_family,
+    int *streams,
+    int *coupled_streams,
+    int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+
+/** Encodes a projection Opus frame.
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+  * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
+  *                                            samples.
+  *                                            This must contain
+  *                                            <code>frame_size*channels</code>
+  *                                            samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
+    OpusProjectionEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a projection Opus frame.
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+  * @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
+  *                                            samples representing (or slightly exceeding) 24-bit values.
+  *                                            This must contain
+  *                                            <code>frame_size*channels</code>
+  *                                            samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode24(
+    OpusProjectionEncoder *st,
+    const opus_int32 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Encodes a projection Opus frame from floating point input.
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+  * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
+  *                                       samples with a normal range of
+  *                                       +/-1.0.
+  *                                       Samples with a range beyond +/-1.0
+  *                                       are supported but will be clipped by
+  *                                       decoders using the integer API and
+  *                                       should only be used if it is known
+  *                                       that the far end supports extended
+  *                                       dynamic range.
+  *                                       This must contain
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+  *                                 signal.
+  *                                 This must be an Opus frame size for the
+  *                                 encoder's sampling rate.
+  *                                 For example, at 48 kHz the permitted values
+  *                                 are 120, 240, 480, 960, 1920, and 2880.
+  *                                 Passing in a duration of less than 10 ms
+  *                                 (480 samples at 48 kHz) will prevent the
+  *                                 encoder from using the LPC or hybrid modes.
+  * @param[out] data <tt>unsigned char*</tt>: Output payload.
+  *                                           This must contain storage for at
+  *                                           least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
+    OpusProjectionEncoder *st,
+    const float *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Frees an <code>OpusProjectionEncoder</code> allocated by
+  * opus_projection_ambisonics_encoder_create().
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
+  */
+OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
+
+
+/** Perform a CTL function on a projection Opus encoder.
+  *
+  * Generally the request and subsequent arguments are generated by a
+  * convenience macro.
+  * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls,
+  *                @ref opus_encoderctls, @ref opus_multistream_ctls, or
+  *                @ref opus_projection_ctls
+  * @see opus_genericctls
+  * @see opus_encoderctls
+  * @see opus_multistream_ctls
+  * @see opus_projection_ctls
+  */
+OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/**@}*/
+
+/**\name Projection decoder functions */
+/**@{*/
+
+/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
+  * @param channels <tt>int</tt>: The total number of output channels.
+  *                               This must be no more than 255.
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @returns The size in bytes on success, or a negative error code
+  *          (see @ref opus_errorcodes) on error.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
+    int channels,
+    int streams,
+    int coupled_streams
+);
+
+
+/** Allocates and initializes a projection decoder state.
+  * Call opus_projection_decoder_destroy() to release
+  * this object when finished.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels to output.
+  *                               This must be at most 255.
+  *                               It may be different from the number of coded
+  *                               channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+  *                         that mapping from coded channels to output channels,
+  *                         as described in @ref opus_projection and
+  *                         @ref opus_projection_ctls.
+  * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+  *                                                  demixing matrix, as
+  *                                                  described in @ref
+  *                                                  opus_projection_ctls.
+  * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+  *                                   code (see @ref opus_errorcodes) on
+  *                                   failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
+    opus_int32 Fs,
+    int channels,
+    int streams,
+    int coupled_streams,
+    unsigned char *demixing_matrix,
+    opus_int32 demixing_matrix_size,
+    int *error
+) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection decoder state object.
+  * The memory pointed to by \a st must be at least the size returned by
+  * opus_projection_decoder_get_size().
+  * This is intended for applications which use their own allocator instead of
+  * malloc.
+  * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+  * @see opus_projection_decoder_create
+  * @see opus_projection_deocder_get_size
+  * @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
+  * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+  *                                This must be one of 8000, 12000, 16000,
+  *                                24000, or 48000.
+  * @param channels <tt>int</tt>: Number of channels to output.
+  *                               This must be at most 255.
+  *                               It may be different from the number of coded
+  *                               channels (<code>streams +
+  *                               coupled_streams</code>).
+  * @param streams <tt>int</tt>: The total number of streams coded in the
+  *                              input.
+  *                              This must be no more than 255.
+  * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+  *                                      (2 channel) streams.
+  *                                      This must be no larger than the total
+  *                                      number of streams.
+  *                                      Additionally, The total number of
+  *                                      coded channels (<code>streams +
+  *                                      coupled_streams</code>) must be no
+  *                                      more than 255.
+  * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+  *                         that mapping from coded channels to output channels,
+  *                         as described in @ref opus_projection and
+  *                         @ref opus_projection_ctls.
+  * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+  *                                                  demixing matrix, as
+  *                                                  described in @ref
+  *                                                  opus_projection_ctls.
+  * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+  *          on failure.
+  */
+OPUS_EXPORT int opus_projection_decoder_init(
+    OpusProjectionDecoder *st,
+    opus_int32 Fs,
+    int channels,
+    int streams,
+    int coupled_streams,
+    unsigned char *demixing_matrix,
+    opus_int32 demixing_matrix_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+
+/** Decode a projection Opus packet.
+  * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+  *                                       samples.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
+    OpusProjectionDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int16 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a projection Opus packet.
+  * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
+  *                                       samples representing (or slightly exceeding) 24-bit values.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode24(
+    OpusProjectionDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int32 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a projection Opus packet with floating point output.
+  * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+  * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+  *                                                Use a <code>NULL</code>
+  *                                                pointer to indicate packet
+  *                                                loss.
+  * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+  * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+  *                                       samples.
+  *                                       This must contain room for
+  *                                       <code>frame_size*channels</code>
+  *                                       samples.
+  * @param frame_size <tt>int</tt>: The number of samples per channel of
+  *                                 available space in \a pcm.
+  *                                 If this is less than the maximum packet duration
+  *                                 (120 ms; 5760 for 48kHz), this function will not be capable
+  *                                 of decoding some packets. In the case of PLC (data==NULL)
+  *                                 or FEC (decode_fec=1), then frame_size needs to be exactly
+  *                                 the duration of audio that is missing, otherwise the
+  *                                 decoder will not be in the optimal state to decode the
+  *                                 next incoming packet. For the PLC and FEC cases, frame_size
+  *                                 <b>must</b> be a multiple of 2.5 ms.
+  * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+  *                                 forward error correction data be decoded.
+  *                                 If no such data is available, the frame is
+  *                                 decoded as if it were lost.
+  * @returns Number of samples decoded on success or a negative error code
+  *          (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
+    OpusProjectionDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    float *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Perform a CTL function on a projection Opus decoder.
+  *
+  * Generally the request and subsequent arguments are generated by a
+  * convenience macro.
+  * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+  * @param request This and all remaining parameters should be replaced by one
+  *                of the convenience macros in @ref opus_genericctls,
+  *                @ref opus_decoderctls, @ref opus_multistream_ctls, or
+  *                @ref opus_projection_ctls.
+  * @see opus_genericctls
+  * @see opus_decoderctls
+  * @see opus_multistream_ctls
+  * @see opus_projection_ctls
+  */
+OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/** Frees an <code>OpusProjectionDecoder</code> allocated by
+  * opus_projection_decoder_create().
+  * @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
+  */
+OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
+
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_PROJECTION_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_types.h b/code/sdk/zhihui/test_opus_frame_to_pcm/include/opus_types.h
new file mode 100644 (file)
index 0000000..7cf6755
--- /dev/null
@@ -0,0 +1,166 @@
+/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
+/* Modified by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* opus_types.h based on ogg_types.h from libogg */
+
+/**
+   @file opus_types.h
+   @brief Opus reference implementation types
+*/
+#ifndef OPUS_TYPES_H
+#define OPUS_TYPES_H
+
+#define opus_int         int                     /* used for counters etc; at least 16 bits */
+#define opus_int64       long long
+#define opus_int8        signed char
+
+#define opus_uint        unsigned int            /* used for counters etc; at least 16 bits */
+#define opus_uint64      unsigned long long
+#define opus_uint8       unsigned char
+
+/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
+#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#include <stdint.h>
+#  undef opus_int64
+#  undef opus_int8
+#  undef opus_uint64
+#  undef opus_uint8
+   typedef int8_t opus_int8;
+   typedef uint8_t opus_uint8;
+   typedef int16_t opus_int16;
+   typedef uint16_t opus_uint16;
+   typedef int32_t opus_int32;
+   typedef uint32_t opus_uint32;
+   typedef int64_t opus_int64;
+   typedef uint64_t opus_uint64;
+#elif defined(_WIN32)
+
+#  if defined(__CYGWIN__)
+#    include <_G_config.h>
+     typedef _G_int32_t opus_int32;
+     typedef _G_uint32_t opus_uint32;
+     typedef _G_int16 opus_int16;
+     typedef _G_uint16 opus_uint16;
+#  elif defined(__MINGW32__)
+     typedef short opus_int16;
+     typedef unsigned short opus_uint16;
+     typedef int opus_int32;
+     typedef unsigned int opus_uint32;
+#  elif defined(__MWERKS__)
+     typedef int opus_int32;
+     typedef unsigned int opus_uint32;
+     typedef short opus_int16;
+     typedef unsigned short opus_uint16;
+#  else
+     /* MSVC/Borland */
+     typedef __int32 opus_int32;
+     typedef unsigned __int32 opus_uint32;
+     typedef __int16 opus_int16;
+     typedef unsigned __int16 opus_uint16;
+#  endif
+
+#elif defined(__MACOS__)
+
+#  include <sys/types.h>
+   typedef SInt16 opus_int16;
+   typedef UInt16 opus_uint16;
+   typedef SInt32 opus_int32;
+   typedef UInt32 opus_uint32;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+#  include <sys/types.h>
+   typedef int16_t opus_int16;
+   typedef u_int16_t opus_uint16;
+   typedef int32_t opus_int32;
+   typedef u_int32_t opus_uint32;
+
+#elif defined(__BEOS__)
+
+   /* Be */
+#  include <inttypes.h>
+   typedef int16 opus_int16;
+   typedef u_int16 opus_uint16;
+   typedef int32_t opus_int32;
+   typedef u_int32_t opus_uint32;
+
+#elif defined (__EMX__)
+
+   /* OS/2 GCC */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined (DJGPP)
+
+   /* DJGPP */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined(R5900)
+
+   /* PS2 EE */
+   typedef int opus_int32;
+   typedef unsigned opus_uint32;
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+
+#elif defined(__SYMBIAN32__)
+
+   /* Symbian GCC */
+   typedef signed short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef signed int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef long opus_int32;
+   typedef unsigned long opus_uint32;
+
+#elif defined(CONFIG_TI_C6X)
+
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#else
+
+   /* Give up, take a reasonable guess */
+   typedef short opus_int16;
+   typedef unsigned short opus_uint16;
+   typedef int opus_int32;
+   typedef unsigned int opus_uint32;
+
+#endif
+
+#endif  /* OPUS_TYPES_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/A2NLSF.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/A2NLSF.c
new file mode 100644 (file)
index 0000000..b487686
--- /dev/null
@@ -0,0 +1,267 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/* Conversion between prediction filter coefficients and NLSFs  */
+/* Requires the order to be an even number                      */
+/* A piecewise linear approximation maps LSF <-> cos(LSF)       */
+/* Therefore the result is not accurate NLSFs, but the two      */
+/* functions are accurate inverses of each other                */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+/* Number of binary divisions, when not in low complexity mode */
+#define BIN_DIV_STEPS_A2NLSF_FIX      3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
+#define MAX_ITERATIONS_A2NLSF_FIX    16
+
+/* Helper function for A2NLSF(..)                    */
+/* Transforms polynomials from cos(n*f) to cos(f)^n  */
+static OPUS_INLINE void silk_A2NLSF_trans_poly(
+    opus_int32          *p,                     /* I/O    Polynomial                                */
+    const opus_int      dd                      /* I      Polynomial order (= filter order / 2 )    */
+)
+{
+    opus_int k, n;
+
+    for( k = 2; k <= dd; k++ ) {
+        for( n = dd; n > k; n-- ) {
+            p[ n - 2 ] -= p[ n ];
+        }
+        p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
+    }
+}
+/* Helper function for A2NLSF(..) */
+/* Polynomial evaluation          */
+static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16     */
+    opus_int32          *p,                     /* I    Polynomial, Q16                         */
+    const opus_int32    x,                      /* I    Evaluation point, Q12                   */
+    const opus_int      dd                      /* I    Order                                   */
+)
+{
+    opus_int   n;
+    opus_int32 x_Q16, y32;
+
+    y32 = p[ dd ];                                  /* Q16 */
+    x_Q16 = silk_LSHIFT( x, 4 );
+
+    if ( opus_likely( 8 == dd ) )
+    {
+        y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
+        y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
+    }
+    else
+    {
+        for( n = dd - 1; n >= 0; n-- ) {
+            y32 = silk_SMLAWW( p[ n ], y32, x_Q16 );    /* Q16 */
+        }
+    }
+    return y32;
+}
+
+static OPUS_INLINE void silk_A2NLSF_init(
+     const opus_int32    *a_Q16,
+     opus_int32          *P,
+     opus_int32          *Q,
+     const opus_int      dd
+)
+{
+    opus_int k;
+
+    /* Convert filter coefs to even and odd polynomials */
+    P[dd] = silk_LSHIFT( 1, 16 );
+    Q[dd] = silk_LSHIFT( 1, 16 );
+    for( k = 0; k < dd; k++ ) {
+        P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ];    /* Q16 */
+        Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ];    /* Q16 */
+    }
+
+    /* Divide out zeros as we have that for even filter orders, */
+    /* z =  1 is always a root in Q, and                        */
+    /* z = -1 is always a root in P                             */
+    for( k = dd; k > 0; k-- ) {
+        P[ k - 1 ] -= P[ k ];
+        Q[ k - 1 ] += Q[ k ];
+    }
+
+    /* Transform polynomials from cos(n*f) to cos(f)^n */
+    silk_A2NLSF_trans_poly( P, dd );
+    silk_A2NLSF_trans_poly( Q, dd );
+}
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
+void silk_A2NLSF(
+    opus_int16                  *NLSF,              /* O    Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
+    opus_int32                  *a_Q16,             /* I/O  Monic whitening filter coefficients in Q16 [d]              */
+    const opus_int              d                   /* I    Filter order (must be even)                                 */
+)
+{
+    opus_int   i, k, m, dd, root_ix, ffrac;
+    opus_int32 xlo, xhi, xmid;
+    opus_int32 ylo, yhi, ymid, thr;
+    opus_int32 nom, den;
+    opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+    opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+    opus_int32 *PQ[ 2 ];
+    opus_int32 *p;
+
+    /* Store pointers to array */
+    PQ[ 0 ] = P;
+    PQ[ 1 ] = Q;
+
+    dd = silk_RSHIFT( d, 1 );
+
+    silk_A2NLSF_init( a_Q16, P, Q, dd );
+
+    /* Find roots, alternating between P and Q */
+    p = P;                          /* Pointer to polynomial */
+
+    xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+
+    if( ylo < 0 ) {
+        /* Set the first NLSF to zero and move on to the next */
+        NLSF[ 0 ] = 0;
+        p = Q;                      /* Pointer to polynomial */
+        ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+        root_ix = 1;                /* Index of current root */
+    } else {
+        root_ix = 0;                /* Index of current root */
+    }
+    k = 1;                          /* Loop counter */
+    i = 0;                          /* Counter for bandwidth expansions applied */
+    thr = 0;
+    while( 1 ) {
+        /* Evaluate polynomial */
+        xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
+        yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
+
+        /* Detect zero crossing */
+        if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
+            if( yhi == 0 ) {
+                /* If the root lies exactly at the end of the current       */
+                /* interval, look for the next root in the next interval    */
+                thr = 1;
+            } else {
+                thr = 0;
+            }
+            /* Binary division */
+            ffrac = -256;
+            for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
+                /* Evaluate polynomial */
+                xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
+                ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
+
+                /* Detect zero crossing */
+                if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
+                    /* Reduce frequency */
+                    xhi = xmid;
+                    yhi = ymid;
+                } else {
+                    /* Increase frequency */
+                    xlo = xmid;
+                    ylo = ymid;
+                    ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
+                }
+            }
+
+            /* Interpolate */
+            if( silk_abs( ylo ) < 65536 ) {
+                /* Avoid dividing by zero */
+                den = ylo - yhi;
+                nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
+                if( den != 0 ) {
+                    ffrac += silk_DIV32( nom, den );
+                }
+            } else {
+                /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
+                ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
+            }
+            NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
+
+            silk_assert( NLSF[ root_ix ] >= 0 );
+
+            root_ix++;        /* Next root */
+            if( root_ix >= d ) {
+                /* Found all roots */
+                break;
+            }
+            /* Alternate pointer to polynomial */
+            p = PQ[ root_ix & 1 ];
+
+            /* Evaluate polynomial */
+            xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
+            ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
+        } else {
+            /* Increment loop counter */
+            k++;
+            xlo = xhi;
+            ylo = yhi;
+            thr = 0;
+
+            if( k > LSF_COS_TAB_SZ_FIX ) {
+                i++;
+                if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
+                    /* Set NLSFs to white spectrum and exit */
+                    NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
+                    for( k = 1; k < d; k++ ) {
+                        NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
+                    }
+                    return;
+                }
+
+                /* Error: Apply progressively more bandwidth expansion and run again */
+                silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
+
+                silk_A2NLSF_init( a_Q16, P, Q, dd );
+                p = P;                            /* Pointer to polynomial */
+                xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+                ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+                if( ylo < 0 ) {
+                    /* Set the first NLSF to zero and move on to the next */
+                    NLSF[ 0 ] = 0;
+                    p = Q;                        /* Pointer to polynomial */
+                    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+                    root_ix = 1;                  /* Index of current root */
+                } else {
+                    root_ix = 0;                  /* Index of current root */
+                }
+                k = 1;                            /* Reset loop counter */
+            }
+        }
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/API.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/API.h
new file mode 100644 (file)
index 0000000..7920218
--- /dev/null
@@ -0,0 +1,150 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_API_H
+#define SILK_API_H
+
+#include "control.h"
+#include "typedef.h"
+#include "errors.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet_private.h"
+#endif
+
+#define SILK_MAX_FRAMES_PER_PACKET  3
+
+/* Struct for TOC (Table of Contents) */
+typedef struct {
+    opus_int    VADFlag;                                /* Voice activity for packet                            */
+    opus_int    VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet              */
+    opus_int    inbandFECFlag;                          /* Flag indicating if packet contains in-band FEC       */
+} silk_TOC_struct;
+
+/****************************************/
+/* Encoder functions                    */
+/****************************************/
+
+/***********************************************/
+/* Get size in bytes of the Silk encoder state */
+/***********************************************/
+opus_int silk_Get_Encoder_Size(                         /* O    Returns error code                              */
+    opus_int                        *encSizeBytes,      /* O    Number of bytes in SILK encoder state           */
+    opus_int                         channels           /* I    Number of channels                              */
+);
+
+/*************************/
+/* Init or reset encoder */
+/*************************/
+opus_int silk_InitEncoder(                              /* O    Returns error code                              */
+    void                            *encState,          /* I/O  State                                           */
+    int                              channels,          /* I    Number of channels                              */
+    int                              arch,              /* I    Run-time architecture                           */
+    silk_EncControlStruct           *encStatus          /* O    Encoder Status                                  */
+);
+
+/**************************/
+/* Encode frame with Silk */
+/**************************/
+/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what                     */
+/* encControl->payloadSize_ms is set to                                                                         */
+opus_int silk_Encode(                                   /* O    Returns error code                              */
+    void                            *encState,          /* I/O  State                                           */
+    silk_EncControlStruct           *encControl,        /* I    Control status                                  */
+    const opus_res                  *samplesIn,         /* I    Speech sample input vector                      */
+    opus_int                        nSamplesIn,         /* I    Number of samples in input vector               */
+    ec_enc                          *psRangeEnc,        /* I/O  Compressor data structure                       */
+    opus_int32                      *nBytesOut,         /* I/O  Number of bytes in payload (input: Max bytes)   */
+    const opus_int                  prefillFlag,        /* I    Flag to indicate prefilling buffers no coding   */
+    int                             activity            /* I    Decision of Opus voice activity detector        */
+);
+
+/****************************************/
+/* Decoder functions                    */
+/****************************************/
+
+
+/***********************************************/
+/* Load OSCE models from external data pointer */
+/***********************************************/
+opus_int silk_LoadOSCEModels(
+    void *decState,                                     /* O    I/O State                                       */
+    const unsigned char *data,                          /* I    pointer to binary blob                          */
+    int len                                             /* I    length of binary blob data                      */
+);
+
+/***********************************************/
+/* Get size in bytes of the Silk decoder state */
+/***********************************************/
+opus_int silk_Get_Decoder_Size(                         /* O    Returns error code                              */
+    opus_int                        *decSizeBytes       /* O    Number of bytes in SILK decoder state           */
+);
+
+/*************************/
+/* Init and Reset decoder */
+/*************************/
+opus_int silk_ResetDecoder(                              /* O    Returns error code                              */
+    void                            *decState            /* I/O  State                                           */
+);
+
+opus_int silk_InitDecoder(                              /* O    Returns error code                              */
+    void                            *decState           /* I/O  State                                           */
+);
+
+/******************/
+/* Decode a frame */
+/******************/
+opus_int silk_Decode(                                   /* O    Returns error code                              */
+    void*                           decState,           /* I/O  State                                           */
+    silk_DecControlStruct*          decControl,         /* I/O  Control Structure                               */
+    opus_int                        lostFlag,           /* I    0: no loss, 1 loss, 2 decode fec                */
+    opus_int                        newPacketFlag,      /* I    Indicates first decoder call for this packet    */
+    ec_dec                          *psRangeDec,        /* I/O  Compressor data structure                       */
+    opus_res                        *samplesOut,        /* O    Decoded output speech vector                    */
+    opus_int32                      *nSamplesOut,       /* O    Number of samples decoded                       */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                  *lpcnet,
+#endif
+    int                             arch                /* I    Run-time architecture                           */
+);
+
+#if 0
+/**************************************/
+/* Get table of contents for a packet */
+/**************************************/
+opus_int silk_get_TOC(
+    const opus_uint8                *payload,           /* I    Payload data                                */
+    const opus_int                  nBytesIn,           /* I    Number of input bytes                       */
+    const opus_int                  nFramesPerPayload,  /* I    Number of SILK frames per payload           */
+    silk_TOC_struct                 *Silk_TOC           /* O    Type of content                             */
+);
+#endif
+
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/CNG.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/CNG.c
new file mode 100644 (file)
index 0000000..2a91009
--- /dev/null
@@ -0,0 +1,188 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+
+/* Generates excitation for CNG LPC synthesis */
+static OPUS_INLINE void silk_CNG_exc(
+    opus_int32                       exc_Q14[],          /* O    CNG excitation signal Q10                   */
+    opus_int32                       exc_buf_Q14[],      /* I    Random samples buffer Q10                   */
+    opus_int                         length,             /* I    Length                                      */
+    opus_int32                       *rand_seed          /* I/O  Seed to random index generator              */
+)
+{
+    opus_int32 seed;
+    opus_int   i, idx, exc_mask;
+
+    exc_mask = CNG_BUF_MASK_MAX;
+    while( exc_mask > length ) {
+        exc_mask = silk_RSHIFT( exc_mask, 1 );
+    }
+
+    seed = *rand_seed;
+    for( i = 0; i < length; i++ ) {
+        seed = silk_RAND( seed );
+        idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
+        silk_assert( idx >= 0 );
+        silk_assert( idx <= CNG_BUF_MASK_MAX );
+        exc_Q14[ i ] = exc_buf_Q14[ idx ];
+    }
+    *rand_seed = seed;
+}
+
+void silk_CNG_Reset(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state                               */
+)
+{
+    opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
+
+    NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
+    NLSF_acc_Q15 = 0;
+    for( i = 0; i < psDec->LPC_order; i++ ) {
+        NLSF_acc_Q15 += NLSF_step_Q15;
+        psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
+    }
+    psDec->sCNG.CNG_smth_Gain_Q16 = 0;
+    psDec->sCNG.rand_seed = 3176576;
+}
+
+/* Updates CNG estimate, and applies the CNG when packet was lost   */
+void silk_CNG(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
+    silk_decoder_control        *psDecCtrl,                     /* I/O  Decoder control                             */
+    opus_int16                  frame[],                        /* I/O  Signal                                      */
+    opus_int                    length                          /* I    Length of residual                          */
+)
+{
+    opus_int   i, subfr;
+    opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
+    opus_int16 A_Q12[ MAX_LPC_ORDER ];
+    silk_CNG_struct *psCNG = &psDec->sCNG;
+    SAVE_STACK;
+
+    if( psDec->fs_kHz != psCNG->fs_kHz ) {
+        /* Reset state */
+        silk_CNG_Reset( psDec );
+
+        psCNG->fs_kHz = psDec->fs_kHz;
+    }
+    if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
+        /* Update CNG parameters */
+
+        /* Smoothing of LSF's  */
+        for( i = 0; i < psDec->LPC_order; i++ ) {
+            psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
+        }
+        /* Find the subframe with the highest gain */
+        max_Gain_Q16 = 0;
+        subfr        = 0;
+        for( i = 0; i < psDec->nb_subfr; i++ ) {
+            if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
+                max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+                subfr        = i;
+            }
+        }
+        /* Update CNG excitation buffer with excitation from this subframe */
+        silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
+        silk_memcpy(   psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
+
+        /* Smooth gains */
+        for( i = 0; i < psDec->nb_subfr; i++ ) {
+            psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
+            /* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */
+            if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) {
+                psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+            }
+        }
+    }
+
+    /* Add CNG when packet is lost or during DTX */
+    if( psDec->lossCnt ) {
+        VARDECL( opus_int32, CNG_sig_Q14 );
+        ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
+
+        /* Generate CNG excitation */
+        gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
+        if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
+            gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
+            gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+            gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
+        } else {
+            gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
+            gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+            gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
+        }
+        gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
+
+        silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
+
+        /* Convert CNG NLSF to filter representation */
+        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
+
+        /* Generate CNG signal, by synthesis filtering */
+        silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+        celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+        for( i = 0; i < length; i++ ) {
+            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+            LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12[ 1 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12[ 2 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12[ 3 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12[ 4 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12[ 5 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12[ 6 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12[ 7 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12[ 8 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
+            if( psDec->LPC_order == 16 ) {
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
+            }
+
+            /* Update states */
+            CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
+            /* Scale with Gain and add to input signal */
+            frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
+
+        }
+        silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+    } else {
+        silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order *  sizeof( opus_int32 ) );
+    }
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/HP_variable_cutoff.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/HP_variable_cutoff.c
new file mode 100644 (file)
index 0000000..bbe10f0
--- /dev/null
@@ -0,0 +1,77 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef FIXED_POINT
+#include "main_FIX.h"
+#else
+#include "main_FLP.h"
+#endif
+#include "tuning_parameters.h"
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+    silk_encoder_state_Fxx          state_Fxx[]                         /* I/O  Encoder states                              */
+)
+{
+   opus_int   quality_Q15;
+   opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
+   silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn;
+
+   /* Adaptive cutoff frequency: estimate low end of pitch frequency range */
+   if( psEncC1->prevSignalType == TYPE_VOICED ) {
+      /* difference, in log domain */
+      pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag );
+      pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 );
+
+      /* adjustment based on quality */
+      quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ];
+      pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ),
+            pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) );
+
+      /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */
+      delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 );
+      if( delta_freq_Q7 < 0 ) {
+         /* less smoothing for decreasing pitch frequency, to track something close to the minimum */
+         delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 );
+      }
+
+      /* limit delta, to reduce impact of outliers in pitch estimation */
+      delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
+
+      /* update smoother */
+      psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15,
+            silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
+
+      /* limit frequency range */
+      psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15,
+            silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ),
+            silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) );
+   }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/Inlines.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/Inlines.h
new file mode 100644 (file)
index 0000000..02473ae
--- /dev/null
@@ -0,0 +1,180 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/*! \file silk_Inlines.h
+ *  \brief silk_Inlines.h defines OPUS_INLINE signal processing functions.
+ */
+
+#ifndef SILK_FIX_INLINES_H
+#define SILK_FIX_INLINES_H
+
+
+/* count leading zeros of opus_int64 */
+static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in )
+{
+    opus_int32 in_upper;
+
+    in_upper = (opus_int32)silk_RSHIFT64(in, 32);
+    if (in_upper == 0) {
+        /* Search in the lower 32 bits */
+        return 32 + silk_CLZ32( (opus_int32) in );
+    } else {
+        /* Search in the upper 32 bits */
+        return silk_CLZ32( in_upper );
+    }
+}
+
+/* get number of leading zeros and fractional part (the bits right after the leading one */
+static OPUS_INLINE void silk_CLZ_FRAC(
+    opus_int32 in,            /* I  input                               */
+    opus_int32 *lz,           /* O  number of leading zeros             */
+    opus_int32 *frac_Q7       /* O  the 7 bits right after the leading one */
+)
+{
+    opus_int32 lzeros = silk_CLZ32(in);
+
+    * lz = lzeros;
+    * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f;
+}
+
+/* Approximation of square root                                          */
+/* Accuracy: < +/- 10%  for output values > 15                           */
+/*           < +/- 2.5% for output values > 120                          */
+static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x )
+{
+    opus_int32 y, lz, frac_Q7;
+
+    if( x <= 0 ) {
+        return 0;
+    }
+
+    silk_CLZ_FRAC(x, &lz, &frac_Q7);
+
+    if( lz & 1 ) {
+        y = 32768;
+    } else {
+        y = 46214;        /* 46214 = sqrt(2) * 32768 */
+    }
+
+    /* get scaling right */
+    y >>= silk_RSHIFT(lz, 1);
+
+    /* increment using fractional part of input */
+    y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7));
+
+    return y;
+}
+
+/* Divide two int32 values and return result as int32 in a given Q-domain */
+static OPUS_INLINE opus_int32 silk_DIV32_varQ(   /* O    returns a good approximation of "(a32 << Qres) / b32" */
+    const opus_int32     a32,               /* I    numerator (Q0)                  */
+    const opus_int32     b32,               /* I    denominator (Q0)                */
+    const opus_int       Qres               /* I    Q-domain of result (>= 0)       */
+)
+{
+    opus_int   a_headrm, b_headrm, lshift;
+    opus_int32 b32_inv, a32_nrm, b32_nrm, result;
+
+    silk_assert( b32 != 0 );
+    silk_assert( Qres >= 0 );
+
+    /* Compute number of bits head room and normalize inputs */
+    a_headrm = silk_CLZ32( silk_abs(a32) ) - 1;
+    a32_nrm = silk_LSHIFT(a32, a_headrm);                                       /* Q: a_headrm                  */
+    b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+    b32_nrm = silk_LSHIFT(b32, b_headrm);                                       /* Q: b_headrm                  */
+
+    /* Inverse of b32, with 14 bits of precision */
+    b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );   /* Q: 29 + 16 - b_headrm        */
+
+    /* First approximation */
+    result = silk_SMULWB(a32_nrm, b32_inv);                                     /* Q: 29 + a_headrm - b_headrm  */
+
+    /* Compute residual by subtracting product of denominator and first approximation */
+    /* It's OK to overflow because the final value of a32_nrm should always be small */
+    a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 ));  /* Q: a_headrm   */
+
+    /* Refinement */
+    result = silk_SMLAWB(result, a32_nrm, b32_inv);                             /* Q: 29 + a_headrm - b_headrm  */
+
+    /* Convert to Qres domain */
+    lshift = 29 + a_headrm - b_headrm - Qres;
+    if( lshift < 0 ) {
+        return silk_LSHIFT_SAT32(result, -lshift);
+    } else {
+        if( lshift < 32){
+            return silk_RSHIFT(result, lshift);
+        } else {
+            /* Avoid undefined result */
+            return 0;
+        }
+    }
+}
+
+/* Invert int32 value and return result as int32 in a given Q-domain */
+static OPUS_INLINE opus_int32 silk_INVERSE32_varQ(   /* O    returns a good approximation of "(1 << Qres) / b32" */
+    const opus_int32     b32,                   /* I    denominator (Q0)                */
+    const opus_int       Qres                   /* I    Q-domain of result (> 0)        */
+)
+{
+    opus_int   b_headrm, lshift;
+    opus_int32 b32_inv, b32_nrm, err_Q32, result;
+
+    silk_assert( b32 != 0 );
+    silk_assert( Qres > 0 );
+
+    /* Compute number of bits head room and normalize input */
+    b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+    b32_nrm = silk_LSHIFT(b32, b_headrm);                                       /* Q: b_headrm                */
+
+    /* Inverse of b32, with 14 bits of precision */
+    b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );   /* Q: 29 + 16 - b_headrm    */
+
+    /* First approximation */
+    result = silk_LSHIFT(b32_inv, 16);                                          /* Q: 61 - b_headrm            */
+
+    /* Compute residual by subtracting product of denominator and first approximation from one */
+    err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 );        /* Q32                        */
+
+    /* Refinement */
+    result = silk_SMLAWW(result, err_Q32, b32_inv);                             /* Q: 61 - b_headrm            */
+
+    /* Convert to Qres domain */
+    lshift = 61 - b_headrm - Qres;
+    if( lshift <= 0 ) {
+        return silk_LSHIFT_SAT32(result, -lshift);
+    } else {
+        if( lshift < 32){
+            return silk_RSHIFT(result, lshift);
+        }else{
+            /* Avoid undefined result */
+            return 0;
+        }
+    }
+}
+
+#endif /* SILK_FIX_INLINES_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_analysis_filter.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_analysis_filter.c
new file mode 100644 (file)
index 0000000..d34b5eb
--- /dev/null
@@ -0,0 +1,111 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "celt_lpc.h"
+
+/*******************************************/
+/* LPC analysis filter                     */
+/* NB! State is kept internally and the    */
+/* filter always starts with zero state    */
+/* first d output samples are set to zero  */
+/*******************************************/
+
+/* OPT: Using celt_fir() for this function should be faster, but it may cause
+   integer overflows in intermediate values (not final results), which the
+   current implementation silences by casting to unsigned. Enabling
+   this should be safe in pretty much all cases, even though it is not technically
+   C89-compliant. */
+#define USE_CELT_FIR 0
+
+void silk_LPC_analysis_filter(
+    opus_int16                  *out,               /* O    Output signal                                               */
+    const opus_int16            *in,                /* I    Input signal                                                */
+    const opus_int16            *B,                 /* I    MA prediction coefficients, Q12 [order]                     */
+    const opus_int32            len,                /* I    Signal length                                               */
+    const opus_int32            d,                  /* I    Filter order                                                */
+    int                         arch                /* I    Run-time architecture                                       */
+)
+{
+    opus_int   j;
+#if defined(FIXED_POINT) && USE_CELT_FIR
+    opus_int16 num[SILK_MAX_ORDER_LPC];
+#else
+    int ix;
+    opus_int32       out32_Q12, out32;
+    const opus_int16 *in_ptr;
+#endif
+
+    celt_assert( d >= 6 );
+    celt_assert( (d & 1) == 0 );
+    celt_assert( d <= len );
+
+#if defined(FIXED_POINT) && USE_CELT_FIR
+    celt_assert( d <= SILK_MAX_ORDER_LPC );
+    for ( j = 0; j < d; j++ ) {
+        num[ j ] = -B[ j ];
+    }
+    celt_fir( in + d, num, out + d, len - d, d, arch );
+    for ( j = 0; j < d; j++ ) {
+        out[ j ] = 0;
+    }
+#else
+    (void)arch;
+    for( ix = d; ix < len; ix++ ) {
+        in_ptr = &in[ ix - 1 ];
+
+        out32_Q12 = silk_SMULBB( in_ptr[  0 ], B[ 0 ] );
+        /* Allowing wrap around so that two wraps can cancel each other. The rare
+           cases where the result wraps around can only be triggered by invalid streams*/
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
+        out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
+        for( j = 6; j < d; j += 2 ) {
+            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j     ], B[ j     ] );
+            out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
+        }
+
+        /* Subtract prediction */
+        out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
+
+        /* Scale to Q0 */
+        out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
+
+        /* Saturate output */
+        out[ ix ] = (opus_int16)silk_SAT16( out32 );
+    }
+
+    /* Set first d output samples to zero */
+    silk_memset( out, 0, d * sizeof( opus_int16 ) );
+#endif
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_fit.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_fit.c
new file mode 100644 (file)
index 0000000..c0690a1
--- /dev/null
@@ -0,0 +1,82 @@
+/***********************************************************************
+Copyright (c) 2013, Koen Vos. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around.
+   This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                    *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
+)
+{
+    opus_int    i, k, idx = 0;
+    opus_int32    maxabs, absval, chirp_Q16;
+
+    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+    for( i = 0; i < 10; i++ ) {
+        /* Find maximum absolute value and its index */
+        maxabs = 0;
+        for( k = 0; k < d; k++ ) {
+            absval = silk_abs( a_QIN[k] );
+            if( absval > maxabs ) {
+                maxabs = absval;
+                idx    = k;
+            }
+        }
+        maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
+
+        if( maxabs > silk_int16_MAX ) {
+            /* Reduce magnitude of prediction coefficients */
+            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+            chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+                                        silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+            silk_bwexpander_32( a_QIN, d, chirp_Q16 );
+        } else {
+            break;
+        }
+    }
+
+    if( i == 10 ) {
+        /* Reached the last iteration, clip the coefficients */
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
+            a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
+        }
+    } else {
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
+        }
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain.c
new file mode 100644 (file)
index 0000000..a3746a6
--- /dev/null
@@ -0,0 +1,141 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "define.h"
+
+#define QA                          24
+#define A_LIMIT                     SILK_FIX_CONST( 0.99975, QA )
+
+#define MUL32_FRAC_Q(a32, b32, Q)   ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
+
+/* Compute inverse of LPC prediction gain, and                          */
+/* test if LPC coefficients are stable (all poles within unit circle)   */
+static opus_int32 LPC_inverse_pred_gain_QA_c(               /* O   Returns inverse prediction gain in energy domain, Q30    */
+    opus_int32           A_QA[ SILK_MAX_ORDER_LPC ],        /* I   Prediction coefficients                                  */
+    const opus_int       order                              /* I   Prediction order                                         */
+)
+{
+    opus_int   k, n, mult2Q;
+    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
+
+    invGain_Q30 = SILK_FIX_CONST( 1, 30 );
+    for( k = order - 1; k > 0; k-- ) {
+        /* Check for stability */
+        if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+            return 0;
+        }
+
+        /* Set RC equal to negated AR coef */
+        rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
+
+        /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
+        rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+        silk_assert( rc_mult1_Q30 > ( 1 << 15 ) );                   /* reduce A_LIMIT if fails */
+        silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
+
+        /* Update inverse gain */
+        /* invGain_Q30 range: [ 0 : 2^30 ] */
+        invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+        silk_assert( invGain_Q30 >= 0           );
+        silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+        if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+            return 0;
+        }
+
+        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+
+        /* Update AR coefficient */
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            opus_int64 tmp64;
+            tmp1 = A_QA[ n ];
+            tmp2 = A_QA[ k - n - 1 ];
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+                  MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ n ] = ( opus_int32 )tmp64;
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+                  MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
+        }
+    }
+
+    /* Check for stability */
+    if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+        return 0;
+    }
+
+    /* Set RC equal to negated AR coef */
+    rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
+
+    /* Range: [ 1 : 2^30 ] */
+    rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+
+    /* Update inverse gain */
+    /* Range: [ 0 : 2^30 ] */
+    invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+    silk_assert( invGain_Q30 >= 0           );
+    silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+    if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+        return 0;
+    }
+
+    return invGain_Q30;
+}
+
+/* For input in Q12 domain */
+opus_int32 silk_LPC_inverse_pred_gain_c(            /* O   Returns inverse prediction gain in energy domain, Q30        */
+    const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
+    const opus_int              order               /* I   Prediction order                                             */
+)
+{
+    opus_int   k;
+    opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
+    opus_int32 DC_resp = 0;
+
+    /* Increase Q domain of the AR coefficients */
+    for( k = 0; k < order; k++ ) {
+        DC_resp += (opus_int32)A_Q12[ k ];
+        Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+    }
+    /* If the DC is unstable, we don't even need to do the full calculations */
+    if( DC_resp >= 4096 ) {
+        return 0;
+    }
+    return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain_arm.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LPC_inv_pred_gain_arm.h
new file mode 100644 (file)
index 0000000..9895b55
--- /dev/null
@@ -0,0 +1,57 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_LPC_INV_PRED_GAIN_ARM_H
+# define SILK_LPC_INV_PRED_GAIN_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_int32 silk_LPC_inverse_pred_gain_neon(         /* O   Returns inverse prediction gain in energy domain, Q30        */
+    const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
+    const opus_int              order               /* I   Prediction order                                             */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+/*Is run-time CPU detection enabled on this platform?*/
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
+#  endif
+# endif
+
+#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LP_variable_cutoff.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/LP_variable_cutoff.c
new file mode 100644 (file)
index 0000000..79112ad
--- /dev/null
@@ -0,0 +1,135 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+    Elliptic/Cauer filters designed with 0.1 dB passband ripple,
+    80 dB minimum stopband attenuation, and
+    [0.95 : 0.15 : 0.35] normalized cut off frequencies.
+*/
+
+#include "main.h"
+
+/* Helper function, interpolates the filter taps */
+static OPUS_INLINE void silk_LP_interpolate_filter_taps(
+    opus_int32           B_Q28[ TRANSITION_NB ],
+    opus_int32           A_Q28[ TRANSITION_NA ],
+    const opus_int       ind,
+    const opus_int32     fac_Q16
+)
+{
+    opus_int nb, na;
+
+    if( ind < TRANSITION_INT_NUM - 1 ) {
+        if( fac_Q16 > 0 ) {
+            if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
+                /* Piece-wise linear interpolation of B and A */
+                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+                    B_Q28[ nb ] = silk_SMLAWB(
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        fac_Q16 );
+                }
+                for( na = 0; na < TRANSITION_NA; na++ ) {
+                    A_Q28[ na ] = silk_SMLAWB(
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        fac_Q16 );
+                }
+            } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
+                silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
+                /* Piece-wise linear interpolation of B and A */
+                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+                    B_Q28[ nb ] = silk_SMLAWB(
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        fac_Q16 - ( (opus_int32)1 << 16 ) );
+                }
+                for( na = 0; na < TRANSITION_NA; na++ ) {
+                    A_Q28[ na ] = silk_SMLAWB(
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        fac_Q16 - ( (opus_int32)1 << 16 ) );
+                }
+            }
+        } else {
+            silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
+            silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
+        }
+    } else {
+        silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
+        silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
+    }
+}
+
+/* Low-pass filter with variable cutoff frequency based on  */
+/* piece-wise linear interpolation between elliptic filters */
+/* Start by setting psEncC->mode <> 0;                      */
+/* Deactivate by setting psEncC->mode = 0;                  */
+void silk_LP_variable_cutoff(
+    silk_LP_state               *psLP,                          /* I/O  LP filter state                             */
+    opus_int16                  *frame,                         /* I/O  Low-pass filtered output signal             */
+    const opus_int              frame_length                    /* I    Frame length                                */
+)
+{
+    opus_int32   B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
+    opus_int     ind = 0;
+
+    silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
+
+    /* Run filter if needed */
+    if( psLP->mode != 0 ) {
+        /* Calculate index and interpolation factor for interpolation */
+#if( TRANSITION_INT_STEPS == 64 )
+        fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
+#else
+        fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
+#endif
+        ind      = silk_RSHIFT( fac_Q16, 16 );
+        fac_Q16 -= silk_LSHIFT( ind, 16 );
+
+        silk_assert( ind >= 0 );
+        silk_assert( ind < TRANSITION_INT_NUM );
+
+        /* Interpolate filter coefficients */
+        silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
+
+        /* Update transition frame number for next frame */
+        psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
+
+        /* ARMA low-pass filtering */
+        silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
+        silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroCount.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroCount.h
new file mode 100644 (file)
index 0000000..bbeb14b
--- /dev/null
@@ -0,0 +1,709 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SIGPROCFIX_API_MACROCOUNT_H
+#define SIGPROCFIX_API_MACROCOUNT_H
+
+#ifdef    silk_MACRO_COUNT
+#include <stdio.h>
+#define varDefine opus_int64 ops_count = 0;
+
+extern opus_int64 ops_count;
+
+static OPUS_INLINE opus_int64 silk_SaveCount(){
+    return(ops_count);
+}
+
+static OPUS_INLINE opus_int64 silk_SaveResetCount(){
+    opus_int64 ret;
+
+    ret = ops_count;
+    ops_count = 0;
+    return(ret);
+}
+
+static OPUS_INLINE silk_PrintCount(){
+    printf("ops_count = %d \n ", (opus_int32)ops_count);
+}
+
+#undef silk_MUL
+static OPUS_INLINE opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 * b32;
+    return ret;
+}
+
+#undef silk_MUL_uint
+static OPUS_INLINE opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
+    opus_uint32 ret;
+    ops_count += 4;
+    ret = a32 * b32;
+    return ret;
+}
+#undef silk_MLA
+static OPUS_INLINE opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 + b32 * c32;
+    return ret;
+}
+
+#undef silk_MLA_uint
+static OPUS_INLINE opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
+    opus_uint32 ret;
+    ops_count += 4;
+    ret = a32 + b32 * c32;
+    return ret;
+}
+
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 5;
+    ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+    return ret;
+}
+#undef    silk_SMLAWB
+static OPUS_INLINE opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 5;
+    ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)));
+    return ret;
+}
+
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+    return ret;
+}
+#undef silk_SMLAWT
+static OPUS_INLINE opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+    return ret;
+}
+
+#undef silk_SMULBB
+static OPUS_INLINE opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32);
+    return ret;
+}
+#undef silk_SMLABB
+static OPUS_INLINE opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+    return ret;
+}
+
+#undef silk_SMULBT
+static OPUS_INLINE opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16);
+    return ret;
+}
+
+#undef silk_SMLABT
+static OPUS_INLINE opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+    return ret;
+}
+
+#undef silk_SMULTT
+static OPUS_INLINE opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = (a32 >> 16) * (b32 >> 16);
+    return ret;
+}
+
+#undef    silk_SMLATT
+static OPUS_INLINE opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + (b32 >> 16) * (c32 >> 16);
+    return ret;
+}
+
+
+/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
+#undef    silk_MLA_ovflw
+#define silk_MLA_ovflw silk_MLA
+
+#undef silk_SMLABB_ovflw
+#define silk_SMLABB_ovflw silk_SMLABB
+
+#undef silk_SMLABT_ovflw
+#define silk_SMLABT_ovflw silk_SMLABT
+
+#undef silk_SMLATT_ovflw
+#define silk_SMLATT_ovflw silk_SMLATT
+
+#undef silk_SMLAWB_ovflw
+#define silk_SMLAWB_ovflw silk_SMLAWB
+
+#undef silk_SMLAWT_ovflw
+#define silk_SMLAWT_ovflw silk_SMLAWT
+
+#undef silk_SMULL
+static OPUS_INLINE opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){
+    opus_int64 ret;
+    ops_count += 8;
+    ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32));
+    return ret;
+}
+
+#undef    silk_SMLAL
+static OPUS_INLINE opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){
+    opus_int64 ret;
+    ops_count += 8;
+    ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32));
+    return ret;
+}
+#undef    silk_SMLALBB
+static OPUS_INLINE opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){
+    opus_int64 ret;
+    ops_count += 4;
+    ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16));
+    return ret;
+}
+
+#undef    SigProcFIX_CLZ16
+static OPUS_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16)
+{
+    opus_int32 out32 = 0;
+    ops_count += 10;
+    if( in16 == 0 ) {
+        return 16;
+    }
+    /* test nibbles */
+    if( in16 & 0xFF00 ) {
+        if( in16 & 0xF000 ) {
+            in16 >>= 12;
+        } else {
+            out32 += 4;
+            in16 >>= 8;
+        }
+    } else {
+        if( in16 & 0xFFF0 ) {
+            out32 += 8;
+            in16 >>= 4;
+        } else {
+            out32 += 12;
+        }
+    }
+    /* test bits and return */
+    if( in16 & 0xC ) {
+        if( in16 & 0x8 )
+            return out32 + 0;
+        else
+            return out32 + 1;
+    } else {
+        if( in16 & 0xE )
+            return out32 + 2;
+        else
+            return out32 + 3;
+    }
+}
+
+#undef SigProcFIX_CLZ32
+static OPUS_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32)
+{
+    /* test highest 16 bits and convert to opus_int16 */
+    ops_count += 2;
+    if( in32 & 0xFFFF0000 ) {
+        return SigProcFIX_CLZ16((opus_int16)(in32 >> 16));
+    } else {
+        return SigProcFIX_CLZ16((opus_int16)in32) + 16;
+    }
+}
+
+#undef silk_DIV32
+static OPUS_INLINE opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
+    ops_count += 64;
+    return a32 / b32;
+}
+
+#undef silk_DIV32_16
+static OPUS_INLINE opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
+    ops_count += 32;
+    return a32 / b32;
+}
+
+#undef silk_SAT8
+static OPUS_INLINE opus_int8 silk_SAT8(opus_int64 a){
+    opus_int8 tmp;
+    ops_count += 1;
+    tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX  : \
+                    ((a) < silk_int8_MIN ? silk_int8_MIN  : (a)));
+    return(tmp);
+}
+
+#undef silk_SAT16
+static OPUS_INLINE opus_int16 silk_SAT16(opus_int64 a){
+    opus_int16 tmp;
+    ops_count += 1;
+    tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX  : \
+                     ((a) < silk_int16_MIN ? silk_int16_MIN  : (a)));
+    return(tmp);
+}
+#undef silk_SAT32
+static OPUS_INLINE opus_int32 silk_SAT32(opus_int64 a){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX  : \
+                     ((a) < silk_int32_MIN ? silk_int32_MIN  : (a)));
+    return(tmp);
+}
+#undef silk_POS_SAT32
+static OPUS_INLINE opus_int32 silk_POS_SAT32(opus_int64 a){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a));
+    return(tmp);
+}
+
+#undef silk_ADD_POS_SAT8
+static OPUS_INLINE opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){
+    opus_int8 tmp;
+    ops_count += 1;
+    tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX  : ((a)+(b)));
+    return(tmp);
+}
+#undef silk_ADD_POS_SAT16
+static OPUS_INLINE opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){
+    opus_int16 tmp;
+    ops_count += 1;
+    tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)));
+    return(tmp);
+}
+
+#undef silk_ADD_POS_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)));
+    return(tmp);
+}
+
+#undef    silk_LSHIFT8
+static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
+    opus_int8 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT16
+static OPUS_INLINE opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT32
+static OPUS_INLINE opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT64
+static OPUS_INLINE opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
+    ops_count += 1;
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_ovflw
+static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
+    ops_count += 1;
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+
+#undef    silk_RSHIFT8
+static OPUS_INLINE opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT16
+static OPUS_INLINE opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT32
+static OPUS_INLINE opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT64
+static OPUS_INLINE opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+
+#undef    silk_RSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+
+#undef    silk_ADD_LSHIFT
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_LSHIFT32
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_LSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_RSHIFT
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_ADD_RSHIFT32
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_ADD_RSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_SUB_LSHIFT32
+static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_SUB_RSHIFT32
+static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+
+#undef    silk_RSHIFT_ROUND
+static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 3;
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+#undef    silk_RSHIFT_ROUND64
+static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
+    opus_int64 ret;
+    ops_count += 6;
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+#undef    silk_abs_int64
+static OPUS_INLINE opus_int64 silk_abs_int64(opus_int64 a){
+    ops_count += 1;
+    return (((a) >  0)  ? (a) : -(a));            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/
+}
+
+#undef    silk_abs_int32
+static OPUS_INLINE opus_int32 silk_abs_int32(opus_int32 a){
+    ops_count += 1;
+    return silk_abs(a);
+}
+
+
+#undef silk_min
+static silk_min(a, b){
+    ops_count += 1;
+    return (((a) < (b)) ? (a) :  (b));
+}
+#undef silk_max
+static silk_max(a, b){
+    ops_count += 1;
+    return (((a) > (b)) ? (a) :  (b));
+}
+#undef silk_sign
+static silk_sign(a){
+    ops_count += 1;
+    return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ));
+}
+
+#undef    silk_ADD16
+static OPUS_INLINE opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_ADD32
+static OPUS_INLINE opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_ADD64
+static OPUS_INLINE opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+    ops_count += 2;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_SUB16
+static OPUS_INLINE opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a - b;
+    return ret;
+}
+
+#undef    silk_SUB32
+static OPUS_INLINE opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - b;
+    return ret;
+}
+
+#undef    silk_SUB64
+static OPUS_INLINE opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+    ops_count += 2;
+    ret = a - b;
+    return ret;
+}
+
+#undef silk_ADD_SAT16
+static OPUS_INLINE opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
+    opus_int16 res;
+    /* Nb will be counted in AKP_add32 and silk_SAT16*/
+    res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
+    return res;
+}
+
+#undef silk_ADD_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
+    opus_int32 res;
+    ops_count += 1;
+    res =    ((((a32) + (b32)) & 0x80000000) == 0 ?                                    \
+            ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) :    \
+            ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
+    return res;
+}
+
+#undef silk_ADD_SAT64
+static OPUS_INLINE opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
+    opus_int64 res;
+    ops_count += 1;
+    res =    ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                \
+            ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) :    \
+            ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+    return res;
+}
+
+#undef silk_SUB_SAT16
+static OPUS_INLINE opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
+    opus_int16 res;
+    silk_assert(0);
+    /* Nb will be counted in sub-macros*/
+    res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
+    return res;
+}
+
+#undef silk_SUB_SAT32
+static OPUS_INLINE opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
+    opus_int32 res;
+    ops_count += 1;
+    res =     ((((a32)-(b32)) & 0x80000000) == 0 ?                                            \
+            (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) :    \
+            ((((a32)^0x80000000) & (b32)  & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
+    return res;
+}
+
+#undef silk_SUB_SAT64
+static OPUS_INLINE opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
+    opus_int64 res;
+    ops_count += 1;
+    res =    ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                        \
+            (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) :    \
+            ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+
+    return res;
+}
+
+#undef    silk_SMULWW
+static OPUS_INLINE opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    /* Nb will be counted in sub-macros*/
+    ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16));
+    return ret;
+}
+
+#undef    silk_SMLAWW
+static OPUS_INLINE opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    /* Nb will be counted in sub-macros*/
+    ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16));
+    return ret;
+}
+
+#undef    silk_min_int
+static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+
+#undef    silk_min_16
+static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+#undef    silk_min_32
+static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+#undef    silk_min_64
+static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+#undef    silk_max_int
+static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+#undef    silk_max_16
+static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+#undef    silk_max_32
+static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+
+#undef    silk_max_64
+static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+
+
+#undef silk_LIMIT_int
+static OPUS_INLINE opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2)
+{
+    opus_int ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+    return(ret);
+}
+
+#undef silk_LIMIT_16
+static OPUS_INLINE opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2)
+{
+    opus_int16 ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+return(ret);
+}
+
+
+#undef silk_LIMIT_32
+static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+{
+    opus_int32 ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+    return(ret);
+}
+
+#else
+#define varDefine
+#define silk_SaveCount()
+
+#endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroDebug.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/MacroDebug.h
new file mode 100644 (file)
index 0000000..3110da9
--- /dev/null
@@ -0,0 +1,945 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (C) 2012 Xiph.Org Foundation
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef MACRO_DEBUG_H
+#define MACRO_DEBUG_H
+
+/* Redefine macro functions with extensive assertion in DEBUG mode.
+   As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
+
+#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT)
+
+#undef silk_ADD16
+#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){
+    opus_int16 ret;
+
+    ret = a + b;
+    if ( ret != silk_ADD_SAT16( a, b ) )
+    {
+        fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_ADD32
+#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){
+    opus_int32 ret;
+
+    ret = (opus_int32)((opus_uint32)a + (opus_uint32)b);
+    if ( ret != silk_ADD_SAT32( a, b ) )
+    {
+        fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_ADD64
+#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){
+    opus_int64 ret;
+
+    ret = a + b;
+    if ( ret != silk_ADD_SAT64( a, b ) )
+    {
+        fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SUB16
+#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){
+    opus_int16 ret;
+
+    ret = a - b;
+    if ( ret != silk_SUB_SAT16( a, b ) )
+    {
+        fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SUB32
+#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){
+    opus_int64 ret;
+
+    ret = a - (opus_int64)b;
+    if ( ret != silk_SUB_SAT32( a, b ) )
+    {
+        fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SUB64
+#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){
+    opus_int64 ret;
+
+    ret = a - b;
+    if ( ret != silk_SUB_SAT64( a, b ) )
+    {
+        fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_ADD_SAT16
+#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) {
+    opus_int16 res;
+    res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
+    if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) )
+    {
+        fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_ADD_SAT32
+#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    opus_int32 res;
+    res =   ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ?       \
+            ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
+            ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
+    if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) )
+    {
+        fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_ADD_SAT64
+#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) {
+    opus_int64 res;
+    int        fail = 0;
+    res =   ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                 \
+            ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
+            ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+    if( res != a64 + b64 ) {
+        /* Check that we saturated to the correct extreme value */
+        if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+               ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) )
+        {
+            fail = 1;
+        }
+    } else {
+        /* Saturation not necessary */
+        fail = res != a64 + b64;
+    }
+    if ( fail )
+    {
+        fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_SUB_SAT16
+#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) {
+    opus_int16 res;
+    res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
+    if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) )
+    {
+        fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_SUB_SAT32
+#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) {
+    opus_int32 res;
+    res =   ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ?                \
+            (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
+            ((((a32)^0x80000000) & (b32)  & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
+    if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) )
+    {
+        fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_SUB_SAT64
+#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) {
+    opus_int64 res;
+    int        fail = 0;
+    res =   ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                    \
+            (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
+            ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+    if( res != a64 - b64 ) {
+        /* Check that we saturated to the correct extreme value */
+        if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+              ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ))
+        {
+            fail = 1;
+        }
+    } else {
+        /* Saturation not necessary */
+        fail = res != a64 - b64;
+    }
+    if ( fail )
+    {
+        fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return res;
+}
+
+#undef silk_MUL
+#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    opus_int32 ret;
+    opus_int64 ret64;
+    ret = (opus_int32)((opus_uint32)a32 * (opus_uint32)b32);
+    ret64 = (opus_int64)a32 * (opus_int64)b32;
+    if ( (opus_int64)ret != ret64 )
+    {
+        fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_MUL_uint
+#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){
+    opus_uint32 ret;
+    ret = a32 * b32;
+    if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 )
+    {
+        fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_MLA
+#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = a32 + b32 * c32;
+    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
+    {
+        fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_MLA_uint
+#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){
+    opus_uint32 ret;
+    ret = a32 + b32 * c32;
+    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
+    {
+        fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMULWB
+#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    opus_int32 ret;
+    ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+    if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 )
+    {
+        fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMLAWB
+#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = silk_ADD32_ovflw( a32, silk_SMULWB( b32, c32 ) );
+    if ( ret != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) )
+    {
+        fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMULWT
+#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    opus_int32 ret;
+    ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+    if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 )
+    {
+        fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMLAWT
+#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+    if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) )
+    {
+        fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMULL
+#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){
+    opus_int64 ret64;
+    int        fail = 0;
+    ret64 = a64 * b64;
+    if( b64 != 0 ) {
+        fail = a64 != (ret64 / b64);
+    } else if( a64 != 0 ) {
+        fail = b64 != (ret64 / a64);
+    }
+    if ( fail )
+    {
+        fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret64;
+}
+
+/* no checking needed for silk_SMULBB */
+#undef silk_SMLABB
+#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 )
+    {
+        fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+/* no checking needed for silk_SMULBT */
+#undef silk_SMLABT
+#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+    if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) )
+    {
+        fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+/* no checking needed for silk_SMULTT */
+#undef silk_SMLATT
+#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret;
+    ret = a32 + (b32 >> 16) * (c32 >> 16);
+    if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) )
+    {
+        fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_SMULWW
+#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    opus_int32 ret, tmp1, tmp2;
+    opus_int64 ret64;
+    int        fail = 0;
+
+    ret  = silk_SMULWB( a32, b32 );
+    tmp1 = silk_RSHIFT_ROUND( b32, 16 );
+    tmp2 = silk_MUL( a32, tmp1 );
+
+    fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1;
+
+    tmp1 = ret;
+    ret  = silk_ADD32( tmp1, tmp2 );
+    fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 );
+
+    ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
+    fail |= (opus_int64)ret != ret64;
+
+    if ( fail )
+    {
+        fprintf (stderr, "silk_SMULWW(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+
+    return ret;
+}
+
+#undef silk_SMLAWW
+#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+    opus_int32 ret, tmp;
+
+    tmp = silk_SMULWW( b32, c32 );
+    ret = silk_ADD32( a32, tmp );
+    if ( ret != silk_ADD_SAT32( a32, tmp ) )
+    {
+        fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+/* no checking needed for silk_SMULL
+   no checking needed for silk_SMLAL
+   no checking needed for silk_SMLALBB
+   no checking needed for SigProcFIX_CLZ16
+   no checking needed for SigProcFIX_CLZ32*/
+
+#undef silk_DIV32
+#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    if ( b32 == 0 )
+    {
+        fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a32 / b32;
+}
+
+#undef silk_DIV32_16
+#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){
+    int fail = 0;
+    fail |= b32 == 0;
+    fail |= b32 > silk_int16_MAX;
+    fail |= b32 < silk_int16_MIN;
+    if ( fail )
+    {
+        fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a32 / b32;
+}
+
+/* no checking needed for silk_SAT8
+   no checking needed for silk_SAT16
+   no checking needed for silk_SAT32
+   no checking needed for silk_POS_SAT32
+   no checking needed for silk_ADD_POS_SAT8
+   no checking needed for silk_ADD_POS_SAT16
+   no checking needed for silk_ADD_POS_SAT32 */
+
+#undef silk_LSHIFT8
+#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
+    opus_int8 ret;
+    int       fail = 0;
+    ret = (opus_int8)((opus_uint8)a << shift);
+    fail |= shift < 0;
+    fail |= shift >= 8;
+    fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+    if ( fail )
+    {
+        fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_LSHIFT16
+#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
+    opus_int16 ret;
+    int        fail = 0;
+    ret = (opus_int16)((opus_uint16)a << shift);
+    fail |= shift < 0;
+    fail |= shift >= 16;
+    fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+    if ( fail )
+    {
+        fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_LSHIFT32
+#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    int        fail = 0;
+    ret = (opus_int32)((opus_uint32)a << shift);
+    fail |= shift < 0;
+    fail |= shift >= 32;
+    fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+    if ( fail )
+    {
+        fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_LSHIFT64
+#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){
+    opus_int64 ret;
+    int        fail = 0;
+    ret = (opus_int64)((opus_uint64)a << shift);
+    fail |= shift < 0;
+    fail |= shift >= 64;
+    fail |= (ret>>shift) != ((opus_int64)a);
+    if ( fail )
+    {
+        fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_LSHIFT_ovflw
+#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){
+    if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */
+    {
+        fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a << shift;
+}
+
+#undef silk_LSHIFT_uint
+#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
+    opus_uint32 ret;
+    ret = a << shift;
+    if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift))
+    {
+        fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_RSHIFT8
+#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
+    if ( (shift < 0) || (shift>=8) )
+    {
+        fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a >> shift;
+}
+
+#undef silk_RSHIFT16
+#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
+    if ( (shift < 0) || (shift>=16) )
+    {
+        fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a >> shift;
+}
+
+#undef silk_RSHIFT32
+#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
+    if ( (shift < 0) || (shift>=32) )
+    {
+        fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a >> shift;
+}
+
+#undef silk_RSHIFT64
+#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){
+    if ( (shift < 0) || (shift>=64) )
+    {
+        fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a >> shift;
+}
+
+#undef silk_RSHIFT_uint
+#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
+    if ( (shift < 0) || (shift>32) )
+    {
+        fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return a >> shift;
+}
+
+#undef silk_ADD_LSHIFT
+#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){
+    opus_int16 ret;
+    ret = a + (opus_int16)((opus_uint16)b << shift);
+    if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)b) << shift)) )
+    {
+        fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift >= 0 */
+}
+
+#undef silk_ADD_LSHIFT32
+#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    ret = silk_ADD32_ovflw(a, (opus_int32)((opus_uint32)b << shift));
+    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)b) << shift)) )
+    {
+        fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift >= 0 */
+}
+
+#undef silk_ADD_LSHIFT_uint
+#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
+    opus_uint32 ret;
+    ret = a + (b << shift);
+    if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
+    {
+        fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift >= 0 */
+}
+
+#undef silk_ADD_RSHIFT
+#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){
+    opus_int16 ret;
+    ret = a + (b >> shift);
+    if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+    {
+        fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift  > 0 */
+}
+
+#undef silk_ADD_RSHIFT32
+#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    ret = silk_ADD32_ovflw(a, (b >> shift));
+    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+    {
+        fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift  > 0 */
+}
+
+#undef silk_ADD_RSHIFT_uint
+#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
+    opus_uint32 ret;
+    ret = a + (b >> shift);
+    if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+    {
+        fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift  > 0 */
+}
+
+#undef silk_SUB_LSHIFT32
+#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    ret = silk_SUB32_ovflw(a, (opus_int32)((opus_uint32)b << shift));
+    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (opus_int64)(((opus_uint64)b) << shift)) )
+    {
+        fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift >= 0 */
+}
+
+#undef silk_SUB_RSHIFT32
+#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    ret = silk_SUB32_ovflw(a, (b >> shift));
+    if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) )
+    {
+        fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;                /* shift  > 0 */
+}
+
+#undef silk_RSHIFT_ROUND
+#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){
+    opus_int32 ret;
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    /* the macro definition can't handle a shift of zero */
+    if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) )
+    {
+        fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return ret;
+}
+
+#undef silk_RSHIFT_ROUND64
+#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){
+    opus_int64 ret;
+    /* the macro definition can't handle a shift of zero */
+    if ( (shift <= 0) || (shift>=64) )
+    {
+        fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+/* silk_abs is used on floats also, so doesn't work... */
+/*#undef silk_abs
+static OPUS_INLINE opus_int32 silk_abs(opus_int32 a){
+    silk_assert(a != 0x80000000);
+    return (((a) >  0)  ? (a) : -(a));            // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
+}*/
+
+#undef silk_abs_int64
+#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){
+    if ( a == silk_int64_MIN )
+    {
+        fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return (((a) >  0)  ? (a) : -(a));            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+}
+
+#undef silk_abs_int32
+#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){
+    if ( a == silk_int32_MIN )
+    {
+        fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return silk_abs(a);
+}
+
+#undef silk_CHECK_FIT8
+#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){
+    opus_int8 ret;
+    ret = (opus_int8)a;
+    if ( (opus_int64)ret != a )
+    {
+        fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return( ret );
+}
+
+#undef silk_CHECK_FIT16
+#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){
+    opus_int16 ret;
+    ret = (opus_int16)a;
+    if ( (opus_int64)ret != a )
+    {
+        fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return( ret );
+}
+
+#undef silk_CHECK_FIT32
+#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){
+    opus_int32 ret;
+    ret = (opus_int32)a;
+    if ( (opus_int64)ret != a )
+    {
+        fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+        silk_assert( 0 );
+#endif
+    }
+    return( ret );
+}
+
+/* no checking for silk_NSHIFT_MUL_32_32
+   no checking for silk_NSHIFT_MUL_16_16
+   no checking needed for silk_min
+   no checking needed for silk_max
+   no checking needed for silk_sign
+*/
+
+#endif
+#endif /* MACRO_DEBUG_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF2A.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF2A.c
new file mode 100644 (file)
index 0000000..fcddc54
--- /dev/null
@@ -0,0 +1,140 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* conversion between prediction filter coefficients and LSFs   */
+/* order should be even                                         */
+/* a piecewise linear approximation maps LSF <-> cos(LSF)       */
+/* therefore the result is not accurate LSFs, but the two       */
+/* functions are accurate inverses of each other                */
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+#define QA      16
+
+/* helper function for NLSF2A(..) */
+static OPUS_INLINE void silk_NLSF2A_find_poly(
+    opus_int32          *out,      /* O    intermediate polynomial, QA [dd+1]        */
+    const opus_int32    *cLSF,     /* I    vector of interleaved 2*cos(LSFs), QA [d] */
+    opus_int            dd         /* I    polynomial order (= 1/2 * filter order)   */
+)
+{
+    opus_int   k, n;
+    opus_int32 ftmp;
+
+    out[0] = silk_LSHIFT( 1, QA );
+    out[1] = -cLSF[0];
+    for( k = 1; k < dd; k++ ) {
+        ftmp = cLSF[2*k];            /* QA*/
+        out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
+        for( n = k; n > 1; n-- ) {
+            out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
+        }
+        out[1] -= ftmp;
+    }
+}
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+    opus_int16                  *a_Q12,             /* O    monic whitening filter coefficients in Q12,  [ d ]          */
+    const opus_int16            *NLSF,              /* I    normalized line spectral frequencies in Q15, [ d ]          */
+    const opus_int              d,                  /* I    filter order (should be even)                               */
+    int                         arch                /* I    Run-time architecture                                       */
+)
+{
+    /* This ordering was found to maximize quality. It improves numerical accuracy of
+       silk_NLSF2A_find_poly() compared to "standard" ordering. */
+    static const unsigned char ordering16[16] = {
+      0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
+    };
+    static const unsigned char ordering10[10] = {
+      0, 9, 6, 3, 4, 5, 8, 1, 2, 7
+    };
+    const unsigned char *ordering;
+    opus_int   k, i, dd;
+    opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
+    opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+    opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
+    opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
+
+    silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
+    celt_assert( d==10 || d==16 );
+
+    /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
+    ordering = d == 16 ? ordering16 : ordering10;
+    for( k = 0; k < d; k++ ) {
+        silk_assert( NLSF[k] >= 0 );
+
+        /* f_int on a scale 0-127 (rounded down) */
+        f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
+
+        /* f_frac, range: 0..255 */
+        f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
+
+        silk_assert(f_int >= 0);
+        silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
+
+        /* Read start and end value from table */
+        cos_val = silk_LSFCosTab_FIX_Q12[ f_int ];                /* Q12 */
+        delta   = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val;  /* Q12, with a range of 0..200 */
+
+        /* Linear interpolation */
+        cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
+    }
+
+    dd = silk_RSHIFT( d, 1 );
+
+    /* generate even and odd polynomials using convolution */
+    silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
+    silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
+
+    /* convert even and odd polynomials to opus_int32 Q12 filter coefs */
+    for( k = 0; k < dd; k++ ) {
+        Ptmp = P[ k+1 ] + P[ k ];
+        Qtmp = Q[ k+1 ] - Q[ k ];
+
+        /* the Ptmp and Qtmp values at this stage need to fit in int32 */
+        a32_QA1[ k ]     = -Qtmp - Ptmp;        /* QA+1 */
+        a32_QA1[ d-k-1 ] =  Qtmp - Ptmp;        /* QA+1 */
+    }
+
+    /* Convert int32 coefficients to Q12 int16 coefs */
+    silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
+
+    for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+        /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
+        /* on the unscaled coefficients, convert to Q12 and measure again                   */
+        silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
+        for( k = 0; k < d; k++ ) {
+            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );            /* QA+1 -> Q12 */
+        }
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_VQ_weights_laroia.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_VQ_weights_laroia.c
new file mode 100644 (file)
index 0000000..9873bcd
--- /dev/null
@@ -0,0 +1,80 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "define.h"
+#include "SigProc_FIX.h"
+
+/*
+R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
+Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
+Signal Processing, pp. 641-644, 1991.
+*/
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+    opus_int16                  *pNLSFW_Q_OUT,      /* O     Pointer to input vector weights [D]                        */
+    const opus_int16            *pNLSF_Q15,         /* I     Pointer to input vector         [D]                        */
+    const opus_int              D                   /* I     Input vector dimension (even)                              */
+)
+{
+    opus_int   k;
+    opus_int32 tmp1_int, tmp2_int;
+
+    celt_assert( D > 0 );
+    celt_assert( ( D & 1 ) == 0 );
+
+    /* First value */
+    tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
+    tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+    tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
+    tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
+    pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+    silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 );
+
+    /* Main loop */
+    for( k = 1; k < D - 1; k += 2 ) {
+        tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
+        tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+        pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+        silk_assert( pNLSFW_Q_OUT[ k ] > 0 );
+
+        tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
+        tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
+        pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+        silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 );
+    }
+
+    /* Last value */
+    tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
+    tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+    pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+    silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_decode.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_decode.c
new file mode 100644 (file)
index 0000000..eeb0ba8
--- /dev/null
@@ -0,0 +1,93 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Predictive dequantizer for NLSF residuals */
+static OPUS_INLINE void silk_NLSF_residual_dequant(          /* O    Returns RD value in Q30                     */
+          opus_int16         x_Q10[],                        /* O    Output [ order ]                            */
+    const opus_int8          indices[],                      /* I    Quantization indices [ order ]              */
+    const opus_uint8         pred_coef_Q8[],                 /* I    Backward predictor coefs [ order ]          */
+    const opus_int           quant_step_size_Q16,            /* I    Quantization step size                      */
+    const opus_int16         order                           /* I    Number of input values                      */
+)
+{
+    opus_int     i, out_Q10, pred_Q10;
+
+    out_Q10 = 0;
+    for( i = order-1; i >= 0; i-- ) {
+        pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 );
+        out_Q10  = silk_LSHIFT( indices[ i ], 10 );
+        if( out_Q10 > 0 ) {
+            out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+        } else if( out_Q10 < 0 ) {
+            out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+        }
+        out_Q10  = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 );
+        x_Q10[ i ] = out_Q10;
+    }
+}
+
+
+/***********************/
+/* NLSF vector decoder */
+/***********************/
+void silk_NLSF_decode(
+          opus_int16            *pNLSF_Q15,                     /* O    Quantized NLSF vector [ LPC_ORDER ]         */
+          opus_int8             *NLSFIndices,                   /* I    Codebook path vector [ LPC_ORDER + 1 ]      */
+    const silk_NLSF_CB_struct   *psNLSF_CB                      /* I    Codebook object                             */
+)
+{
+    opus_int         i;
+    opus_uint8       pred_Q8[  MAX_LPC_ORDER ];
+    opus_int16       ec_ix[    MAX_LPC_ORDER ];
+    opus_int16       res_Q10[  MAX_LPC_ORDER ];
+    opus_int32       NLSF_Q15_tmp;
+    const opus_uint8 *pCB_element;
+    const opus_int16 *pCB_Wght_Q9;
+
+    /* Unpack entropy table indices and predictor for current CB1 index */
+    silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
+
+    /* Predictive residual dequantizer */
+    silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
+
+    /* Apply inverse square-rooted weights to first stage and add to output */
+    pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+    pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+    for( i = 0; i < psNLSF_CB->order; i++ ) {
+        NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
+        pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
+    }
+
+    /* NLSF stabilization */
+    silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_stabilize.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_stabilize.c
new file mode 100644 (file)
index 0000000..8f3426b
--- /dev/null
@@ -0,0 +1,142 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* NLSF stabilizer:                                         */
+/*                                                          */
+/* - Moves NLSFs further apart if they are too close        */
+/* - Moves NLSFs away from borders if they are too close    */
+/* - High effort to achieve a modification with minimum     */
+/*     Euclidean distance to input vector                   */
+/* - Output are sorted NLSF coefficients                    */
+/*                                                          */
+
+#include "SigProc_FIX.h"
+
+/* Constant Definitions */
+#define MAX_LOOPS        20
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+          opus_int16            *NLSF_Q15,          /* I/O   Unstable/stabilized normalized LSF vector in Q15 [L]       */
+    const opus_int16            *NDeltaMin_Q15,     /* I     Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1]   */
+    const opus_int              L                   /* I     Number of NLSF parameters in the input vector              */
+)
+{
+    opus_int   i, I=0, k, loops;
+    opus_int16 center_freq_Q15;
+    opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;
+
+    /* This is necessary to ensure an output within range of a opus_int16 */
+    silk_assert( NDeltaMin_Q15[L] >= 1 );
+
+    for( loops = 0; loops < MAX_LOOPS; loops++ ) {
+        /**************************/
+        /* Find smallest distance */
+        /**************************/
+        /* First element */
+        min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
+        I = 0;
+        /* Middle elements */
+        for( i = 1; i <= L-1; i++ ) {
+            diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
+            if( diff_Q15 < min_diff_Q15 ) {
+                min_diff_Q15 = diff_Q15;
+                I = i;
+            }
+        }
+        /* Last element */
+        diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
+        if( diff_Q15 < min_diff_Q15 ) {
+            min_diff_Q15 = diff_Q15;
+            I = L;
+        }
+
+        /***************************************************/
+        /* Now check if the smallest distance non-negative */
+        /***************************************************/
+        if( min_diff_Q15 >= 0 ) {
+            return;
+        }
+
+        if( I == 0 ) {
+            /* Move away from lower limit */
+            NLSF_Q15[0] = NDeltaMin_Q15[0];
+
+        } else if( I == L) {
+            /* Move away from higher limit */
+            NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L];
+
+        } else {
+            /* Find the lower extreme for the location of the current center frequency */
+            min_center_Q15 = 0;
+            for( k = 0; k < I; k++ ) {
+                min_center_Q15 += NDeltaMin_Q15[k];
+            }
+            min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+            /* Find the upper extreme for the location of the current center frequency */
+            max_center_Q15 = 1 << 15;
+            for( k = L; k > I; k-- ) {
+                max_center_Q15 -= NDeltaMin_Q15[k];
+            }
+            max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+            /* Move apart, sorted by value, keeping the same center frequency */
+            center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ),
+                min_center_Q15, max_center_Q15 );
+            NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+            NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
+        }
+    }
+
+    /* Safe and simple fall back method, which is less ideal than the above */
+    if( loops == MAX_LOOPS )
+    {
+        /* Insertion sort (fast for already almost sorted arrays):   */
+        /* Best case:  O(n)   for an already sorted array            */
+        /* Worst case: O(n^2) for an inversely sorted array          */
+        silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L );
+
+        /* First NLSF should be no less than NDeltaMin[0] */
+        NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
+
+        /* Keep delta_min distance between the NLSFs */
+        for( i = 1; i < L; i++ )
+            NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) );
+
+        /* Last NLSF should be no higher than 1 - NDeltaMin[L] */
+        NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
+
+        /* Keep NDeltaMin distance between the NLSFs */
+        for( i = L-2; i >= 0; i-- )
+            NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_unpack.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NLSF_unpack.c
new file mode 100644 (file)
index 0000000..d1627dc
--- /dev/null
@@ -0,0 +1,54 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Unpack predictor values and indices for entropy coding tables */
+void silk_NLSF_unpack(
+          opus_int16            ec_ix[],                        /* O    Indices to entropy tables [ LPC_ORDER ]     */
+          opus_uint8            pred_Q8[],                      /* O    LSF predictor [ LPC_ORDER ]                 */
+    const silk_NLSF_CB_struct   *psNLSF_CB,                     /* I    Codebook object                             */
+    const opus_int              CB1_index                       /* I    Index of vector in first LSF codebook       */
+)
+{
+    opus_int   i;
+    opus_uint8 entry;
+    const opus_uint8 *ec_sel_ptr;
+
+    ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ];
+    for( i = 0; i < psNLSF_CB->order; i += 2 ) {
+        entry = *ec_sel_ptr++;
+        ec_ix  [ i     ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+        pred_Q8[ i     ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ];
+        ec_ix  [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+        pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ];
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ.h
new file mode 100644 (file)
index 0000000..c0f2343
--- /dev/null
@@ -0,0 +1,105 @@
+/***********************************************************************
+Copyright (c) 2014 Vidyo.
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+#ifndef SILK_NSQ_H
+#define SILK_NSQ_H
+
+#include "SigProc_FIX.h"
+
+#undef silk_short_prediction_create_arch_coef
+
+static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_c(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
+{
+    opus_int32 out;
+    silk_assert( order == 10 || order == 16 );
+
+    /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+    out = silk_RSHIFT( order, 1 );
+    out = silk_SMLAWB( out, buf32[  0 ], coef16[ 0 ] );
+    out = silk_SMLAWB( out, buf32[ -1 ], coef16[ 1 ] );
+    out = silk_SMLAWB( out, buf32[ -2 ], coef16[ 2 ] );
+    out = silk_SMLAWB( out, buf32[ -3 ], coef16[ 3 ] );
+    out = silk_SMLAWB( out, buf32[ -4 ], coef16[ 4 ] );
+    out = silk_SMLAWB( out, buf32[ -5 ], coef16[ 5 ] );
+    out = silk_SMLAWB( out, buf32[ -6 ], coef16[ 6 ] );
+    out = silk_SMLAWB( out, buf32[ -7 ], coef16[ 7 ] );
+    out = silk_SMLAWB( out, buf32[ -8 ], coef16[ 8 ] );
+    out = silk_SMLAWB( out, buf32[ -9 ], coef16[ 9 ] );
+
+    if( order == 16 )
+    {
+        out = silk_SMLAWB( out, buf32[ -10 ], coef16[ 10 ] );
+        out = silk_SMLAWB( out, buf32[ -11 ], coef16[ 11 ] );
+        out = silk_SMLAWB( out, buf32[ -12 ], coef16[ 12 ] );
+        out = silk_SMLAWB( out, buf32[ -13 ], coef16[ 13 ] );
+        out = silk_SMLAWB( out, buf32[ -14 ], coef16[ 14 ] );
+        out = silk_SMLAWB( out, buf32[ -15 ], coef16[ 15 ] );
+    }
+    return out;
+}
+
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch)  ((void)arch,silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
+
+static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_c(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
+{
+    opus_int32 out;
+    opus_int32 tmp1, tmp2;
+    opus_int j;
+
+    tmp2 = data0[0];
+    tmp1 = data1[0];
+    data1[0] = tmp2;
+
+    out = silk_RSHIFT(order, 1);
+    out = silk_SMLAWB(out, tmp2, coef[0]);
+
+    for (j = 2; j < order; j += 2) {
+        tmp2 = data1[j - 1];
+        data1[j - 1] = tmp1;
+        out = silk_SMLAWB(out, tmp1, coef[j - 1]);
+        tmp1 = data1[j + 0];
+        data1[j + 0] = tmp2;
+        out = silk_SMLAWB(out, tmp2, coef[j]);
+    }
+    data1[order - 1] = tmp1;
+    out = silk_SMLAWB(out, tmp1, coef[order - 1]);
+    /* Q11 -> Q12 */
+    out = silk_LSHIFT32( out, 1 );
+    return out;
+}
+
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch)  ((void)arch,silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order))
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+#include "arm/NSQ_neon.h"
+#endif
+
+#if defined(__mips)
+#include "mips/NSQ_mips.h"
+#endif
+
+#endif /* SILK_NSQ_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_del_dec_arm.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_del_dec_arm.h
new file mode 100644 (file)
index 0000000..0c4fcfc
--- /dev/null
@@ -0,0 +1,100 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_NSQ_DEL_DEC_ARM_H
+#define SILK_NSQ_DEL_DEC_ARM_H
+
+#include "celt/arm/armcpu.h"
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_NSQ_del_dec_neon(
+    const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+    SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+    const opus_int16 *PredCoef_Q12,
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+    const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+    const opus_int LTP_scale_Q14);
+
+#if !defined(OPUS_HAVE_RTCD)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12,  \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,   \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,          \
+                         LTP_scale_Q14, arch)                                \
+    ((void)(arch),                                                           \
+     PRESUME_NEON(silk_NSQ_del_dec)(                                         \
+         psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14,     \
+         AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+         Lambda_Q10, LTP_scale_Q14))
+#endif
+#endif
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+/*Is run-time CPU detection enabled on this platform?*/
+#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
+                                !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+    SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+    const opus_int16 *PredCoef_Q12,
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+    const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+    const opus_int LTP_scale_Q14);
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,  \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,         \
+                         LTP_scale_Q14, arch)                               \
+    ((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])(                        \
+        psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14,     \
+        AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+        Lambda_Q10, LTP_scale_Q14))
+#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12,   \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,    \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,           \
+                         LTP_scale_Q14, arch)                                 \
+    ((void)(arch),                                                            \
+     silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+                           LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,  \
+                           LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,         \
+                           LTP_scale_Q14))
+#endif
+#endif
+
+#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_mips.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_mips.h
new file mode 100644 (file)
index 0000000..fd691ee
--- /dev/null
@@ -0,0 +1,137 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef NSQ_MIPS_H__
+#define NSQ_MIPS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "macros.h"
+
+#if defined (__mips_dsp) && __mips == 32
+
+#define MIPS_MULT __builtin_mips_mult
+#define MIPS_MADD __builtin_mips_madd
+#define MIPS_EXTR_R __builtin_mips_extr_r_w
+
+#define OVERRIDE_silk_noise_shape_quantizer_short_prediction
+/* suddenly performance is worse */
+#define dont_OVERRIDE_silk_NSQ_noise_shape_feedback_loop
+
+/* gets worst performance result */
+#elif defined(__mips_isa_rev) && __mips == 32
+
+static inline long long MIPS_MULT(int a, int b) {
+    return (long long)a * b;
+}
+
+static inline long long MIPS_MADD(long long acc, int a, int b) {
+    return acc + (long long)a * b;
+}
+
+static inline opus_val32 MIPS_EXTR_R(long long acc, int shift) {
+    return (opus_val32)((acc + (1 << shift) / 2) >> shift);
+}
+
+#define OVERRIDE_silk_noise_shape_quantizer_short_prediction
+#define OVERRIDE_silk_NSQ_noise_shape_feedback_loop
+
+#endif
+
+#if defined(OVERRIDE_silk_noise_shape_quantizer_short_prediction)
+
+static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_mips(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
+{
+    opus_int64 out;
+    silk_assert( order == 10 || order == 16 );
+
+    out = MIPS_MULT(      buf32[  0 ], coef16[ 0 ] );
+    out = MIPS_MADD( out, buf32[ -1 ], coef16[ 1 ] );
+    out = MIPS_MADD( out, buf32[ -2 ], coef16[ 2 ] );
+    out = MIPS_MADD( out, buf32[ -3 ], coef16[ 3 ] );
+    out = MIPS_MADD( out, buf32[ -4 ], coef16[ 4 ] );
+    out = MIPS_MADD( out, buf32[ -5 ], coef16[ 5 ] );
+    out = MIPS_MADD( out, buf32[ -6 ], coef16[ 6 ] );
+    out = MIPS_MADD( out, buf32[ -7 ], coef16[ 7 ] );
+    out = MIPS_MADD( out, buf32[ -8 ], coef16[ 8 ] );
+    out = MIPS_MADD( out, buf32[ -9 ], coef16[ 9 ] );
+
+    if( order == 16 )
+    {
+        out = MIPS_MADD( out, buf32[ -10 ], coef16[ 10 ] );
+        out = MIPS_MADD( out, buf32[ -11 ], coef16[ 11 ] );
+        out = MIPS_MADD( out, buf32[ -12 ], coef16[ 12 ] );
+        out = MIPS_MADD( out, buf32[ -13 ], coef16[ 13 ] );
+        out = MIPS_MADD( out, buf32[ -14 ], coef16[ 14 ] );
+        out = MIPS_MADD( out, buf32[ -15 ], coef16[ 15 ] );
+    }
+    return MIPS_EXTR_R(out, 16);
+}
+
+#undef  silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch)  ((void)arch,silk_noise_shape_quantizer_short_prediction_mips(in, coef, order))
+
+#endif /* OVERRIDE_silk_noise_shape_quantizer_short_prediction */
+
+
+#if defined(OVERRIDE_silk_NSQ_noise_shape_feedback_loop)
+
+static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_mips(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
+{
+    opus_int32 out;
+    opus_int32 tmp1, tmp2;
+    opus_int j;
+
+    tmp2 = data0[0];
+    tmp1 = data1[0];
+    data1[0] = tmp2;
+
+    out = MIPS_MULT(tmp2, coef[0]);
+
+    for (j = 2; j < order; j += 2) {
+        tmp2 = data1[j - 1];
+        data1[j - 1] = tmp1;
+        out = MIPS_MADD(out, tmp1, coef[j - 1]);
+        tmp1 = data1[j + 0];
+        data1[j + 0] = tmp2;
+        out = MIPS_MADD(out, tmp2, coef[j]);
+    }
+    data1[order - 1] = tmp1;
+    out = MIPS_MADD(out, tmp1, coef[order - 1]);
+    /* silk_SMLAWB: shift right by 16  &&  Q11 -> Q12: shift left by 1 */
+    return MIPS_EXTR_R( out, (16 - 1) );
+}
+
+#undef  silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch)  ((void)arch,silk_NSQ_noise_shape_feedback_loop_mips(data0, data1, coef, order))
+
+#endif /* OVERRIDE_silk_NSQ_noise_shape_feedback_loop */
+
+#endif /* NSQ_DEL_DEC_MIPSR1_H__ */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_neon.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/NSQ_neon.h
new file mode 100644 (file)
index 0000000..f03d8dd
--- /dev/null
@@ -0,0 +1,114 @@
+/***********************************************************************
+Copyright (C) 2014 Vidyo
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+#ifndef SILK_NSQ_NEON_H
+#define SILK_NSQ_NEON_H
+
+#include "cpu_support.h"
+#include "SigProc_FIX.h"
+
+#undef silk_short_prediction_create_arch_coef
+/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
+static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
+{
+    out[15] = silk_LSHIFT32(in[0], 15);
+    out[14] = silk_LSHIFT32(in[1], 15);
+    out[13] = silk_LSHIFT32(in[2], 15);
+    out[12] = silk_LSHIFT32(in[3], 15);
+    out[11] = silk_LSHIFT32(in[4], 15);
+    out[10] = silk_LSHIFT32(in[5], 15);
+    out[9]  = silk_LSHIFT32(in[6], 15);
+    out[8]  = silk_LSHIFT32(in[7], 15);
+    out[7]  = silk_LSHIFT32(in[8], 15);
+    out[6]  = silk_LSHIFT32(in[9], 15);
+
+    if (order == 16)
+    {
+        out[5] = silk_LSHIFT32(in[10], 15);
+        out[4] = silk_LSHIFT32(in[11], 15);
+        out[3] = silk_LSHIFT32(in[12], 15);
+        out[2] = silk_LSHIFT32(in[13], 15);
+        out[1] = silk_LSHIFT32(in[14], 15);
+        out[0] = silk_LSHIFT32(in[15], 15);
+    }
+    else
+    {
+        out[5] = 0;
+        out[4] = 0;
+        out[3] = 0;
+        out[2] = 0;
+        out[1] = 0;
+        out[0] = 0;
+    }
+}
+
+#if defined(OPUS_ARM_PRESUME_NEON_INTR)
+
+#define silk_short_prediction_create_arch_coef(out, in, order) \
+    (silk_short_prediction_create_arch_coef_neon(out, in, order))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+
+#define silk_short_prediction_create_arch_coef(out, in, order) \
+    do { if (arch >= OPUS_ARCH_ARM_NEON) { silk_short_prediction_create_arch_coef_neon(out, in, order); } } while (0)
+
+#endif
+
+opus_int32 silk_noise_shape_quantizer_short_prediction_neon(const opus_int32 *buf32, const opus_int32 *coef32, opus_int order);
+
+opus_int32 silk_NSQ_noise_shape_feedback_loop_neon(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order);
+
+#if defined(OPUS_ARM_PRESUME_NEON_INTR)
+#undef silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) \
+    ((void)arch,silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order))
+
+#undef silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch)  ((void)arch,silk_NSQ_noise_shape_feedback_loop_neon(data0, data1, coef, order))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+
+/* silk_noise_shape_quantizer_short_prediction implementations take different parameters based on arch
+   (coef vs. coefRev) so can't use the usual IMPL table implementation */
+#undef silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch)  \
+    (arch >= OPUS_ARCH_ARM_NEON ? \
+        silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order) : \
+        silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
+
+extern opus_int32
+ (*const SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[OPUS_ARCHMASK+1])(
+ const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef,
+ opus_int order);
+
+#undef silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) \
+ (SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[(arch)&OPUS_ARCHMASK](data0, data1, \
+ coef, order))
+
+#endif
+
+#endif /* SILK_NSQ_NEON_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.c
new file mode 100644 (file)
index 0000000..26aa889
--- /dev/null
@@ -0,0 +1,493 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+#include "PLC.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#endif
+
+#define NB_ATT 2
+static const opus_int16 HARM_ATT_Q15[NB_ATT]              = { 32440, 31130 }; /* 0.99, 0.95 */
+static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT]  = { 31130, 26214 }; /* 0.95, 0.8 */
+static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
+
+static OPUS_INLINE void silk_PLC_update(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl          /* I/O Decoder control      */
+);
+
+static OPUS_INLINE void silk_PLC_conceal(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                          frame[],            /* O LPC residual signal    */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                      *lpcnet,
+#endif
+    int                                 arch                /* I  Run-time architecture */
+);
+
+
+void silk_PLC_Reset(
+    silk_decoder_state                  *psDec              /* I/O Decoder state        */
+)
+{
+    psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 );
+    psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
+    psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
+    psDec->sPLC.subfr_length = 20;
+    psDec->sPLC.nb_subfr = 2;
+}
+
+void silk_PLC(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                          frame[],            /* I/O  signal              */
+    opus_int                            lost,               /* I Loss flag              */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                      *lpcnet,
+#endif
+    int                                 arch                /* I Run-time architecture  */
+)
+{
+    /* PLC control function */
+    if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
+        silk_PLC_Reset( psDec );
+        psDec->sPLC.fs_kHz = psDec->fs_kHz;
+    }
+
+    if( lost ) {
+        /****************************/
+        /* Generate Signal          */
+        /****************************/
+        silk_PLC_conceal( psDec, psDecCtrl, frame,
+#ifdef ENABLE_DEEP_PLC
+            lpcnet,
+#endif
+            arch );
+
+        psDec->lossCnt++;
+    } else {
+        /****************************/
+        /* Update state             */
+        /****************************/
+        silk_PLC_update( psDec, psDecCtrl );
+#ifdef ENABLE_DEEP_PLC
+        if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) {
+            int k;
+            for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+                lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+            }
+        }
+#endif
+    }
+}
+
+/**************************************************/
+/* Update state of PLC                            */
+/**************************************************/
+static OPUS_INLINE void silk_PLC_update(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl          /* I/O Decoder control      */
+)
+{
+    opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
+    opus_int   i, j;
+    silk_PLC_struct *psPLC;
+
+    psPLC = &psDec->sPLC;
+
+    /* Update parameters used in case of packet loss */
+    psDec->prevSignalType = psDec->indices.signalType;
+    LTP_Gain_Q14 = 0;
+    if( psDec->indices.signalType == TYPE_VOICED ) {
+        /* Find the parameters for the last subframe which contains a pitch pulse */
+        for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
+            if( j == psDec->nb_subfr ) {
+                break;
+            }
+            temp_LTP_Gain_Q14 = 0;
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER  + i ];
+            }
+            if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
+                LTP_Gain_Q14 = temp_LTP_Gain_Q14;
+                silk_memcpy( psPLC->LTPCoef_Q14,
+                    &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
+                    LTP_ORDER * sizeof( opus_int16 ) );
+
+                psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
+            }
+        }
+
+        silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+        psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
+
+        /* Limit LT coefs */
+        if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
+            opus_int   scale_Q10;
+            opus_int32 tmp;
+
+            tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
+            scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
+            }
+        } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
+            opus_int   scale_Q14;
+            opus_int32 tmp;
+
+            tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
+            scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
+            }
+        }
+    } else {
+        psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
+        silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
+    }
+
+    /* Save LPC coefficients */
+    silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
+    psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
+
+    /* Save last two gains */
+    silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
+
+    psPLC->subfr_length = psDec->subfr_length;
+    psPLC->nb_subfr = psDec->nb_subfr;
+}
+
+static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
+      const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
+{
+    int i, k;
+    VARDECL( opus_int16, exc_buf );
+    opus_int16 *exc_buf_ptr;
+    SAVE_STACK;
+    ALLOC( exc_buf, 2*subfr_length, opus_int16 );
+    /* Find random noise component */
+    /* Scale previous excitation signal */
+    exc_buf_ptr = exc_buf;
+    for( k = 0; k < 2; k++ ) {
+        for( i = 0; i < subfr_length; i++ ) {
+            exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
+                silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
+        }
+        exc_buf_ptr += subfr_length;
+    }
+    /* Find the subframe with lowest energy of the last two and use that as random noise generator */
+    silk_sum_sqr_shift( energy1, shift1, exc_buf,                  subfr_length );
+    silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
+    RESTORE_STACK;
+}
+
+static OPUS_INLINE void silk_PLC_conceal(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                          frame[],            /* O LPC residual signal    */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                      *lpcnet,
+#endif
+    int                                 arch                /* I Run-time architecture  */
+)
+{
+    opus_int   i, j, k;
+    opus_int   lag, idx, sLTP_buf_idx, shift1, shift2;
+    opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
+    opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
+    opus_int32 LPC_pred_Q10, LTP_pred_Q12;
+    opus_int16 rand_scale_Q14;
+    opus_int16 *B_Q14;
+    opus_int32 *sLPC_Q14_ptr;
+    opus_int16 A_Q12[ MAX_LPC_ORDER ];
+#ifdef SMALL_FOOTPRINT
+    opus_int16 *sLTP;
+#else
+    VARDECL( opus_int16, sLTP );
+#endif
+    VARDECL( opus_int32, sLTP_Q14 );
+    silk_PLC_struct *psPLC = &psDec->sPLC;
+    opus_int32 prevGain_Q10[2];
+    SAVE_STACK;
+
+    ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
+#ifdef SMALL_FOOTPRINT
+    /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
+    sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
+#else
+    ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
+#endif
+
+    prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
+    prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
+
+    if( psDec->first_frame_after_reset ) {
+       silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
+    }
+
+    silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);
+
+    if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
+        /* First sub-frame has lowest energy */
+        rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
+    } else {
+        /* Second sub-frame has lowest energy */
+        rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
+    }
+
+    /* Set up Gain to random noise component */
+    B_Q14          = psPLC->LTPCoef_Q14;
+    rand_scale_Q14 = psPLC->randScale_Q14;
+
+    /* Set up attenuation gains */
+    harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+    if( psDec->prevSignalType == TYPE_VOICED ) {
+        rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[  silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+    } else {
+        rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+    }
+
+    /* LPC concealment. Apply BWE to previous LPC */
+    silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
+
+    /* Preload LPC coefficients to array on stack. Gives small performance gain */
+    silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+
+    /* First Lost frame */
+    if( psDec->lossCnt == 0 ) {
+        rand_scale_Q14 = 1 << 14;
+
+        /* Reduce random noise Gain for voiced frames */
+        if( psDec->prevSignalType == TYPE_VOICED ) {
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                rand_scale_Q14 -= B_Q14[ i ];
+            }
+            rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
+            rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
+        } else {
+            /* Reduce random noise for unvoiced frames with high LPC gain */
+            opus_int32 invGain_Q30, down_scale_Q30;
+
+            invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
+
+            down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
+            down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
+            down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
+
+            rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
+        }
+    }
+
+    rand_seed    = psPLC->rand_seed;
+    lag          = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+    sLTP_buf_idx = psDec->ltp_mem_length;
+
+    /* Rewhiten LTP state */
+    idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
+    celt_assert( idx > 0 );
+    silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
+    /* Scale LTP state */
+    inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
+    inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
+    for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
+        sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
+    }
+
+    /***************************/
+    /* LTP synthesis filtering */
+    /***************************/
+    for( k = 0; k < psDec->nb_subfr; k++ ) {
+        /* Set up pointer */
+        pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            /* Unrolled loop */
+            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+            LTP_pred_Q12 = 2;
+            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
+            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
+            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
+            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
+            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
+            pred_lag_ptr++;
+
+            /* Generate LPC excitation */
+            rand_seed = silk_RAND( rand_seed );
+            idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
+            sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
+            sLTP_buf_idx++;
+        }
+
+        /* Gradually reduce LTP gain */
+        for( j = 0; j < LTP_ORDER; j++ ) {
+            B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
+        }
+        /* Gradually reduce excitation gain */
+        rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
+
+        /* Slowly increase pitch lag */
+        psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
+        psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
+        lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+    }
+
+    /***************************/
+    /* LPC synthesis filtering */
+    /***************************/
+    sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
+
+    /* Copy LPC state */
+    silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+    celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+    for( i = 0; i < psDec->frame_length; i++ ) {
+        /* partly unrolled */
+        /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+        LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  2 ], A_Q12[ 1 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  3 ], A_Q12[ 2 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  4 ], A_Q12[ 3 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  5 ], A_Q12[ 4 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  6 ], A_Q12[ 5 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  7 ], A_Q12[ 6 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  8 ], A_Q12[ 7 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  9 ], A_Q12[ 8 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
+        for( j = 10; j < psDec->LPC_order; j++ ) {
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
+        }
+
+        /* Add prediction to LPC excitation */
+        sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
+                                            silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));
+
+        /* Scale with Gain */
+        frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
+    }
+#ifdef ENABLE_DEEP_PLC
+    if ( lpcnet != NULL && lpcnet->loaded && psDec->sPLC.fs_kHz == 16 ) {
+        int run_deep_plc = psDec->sPLC.enable_deep_plc || lpcnet->fec_fill_pos != 0;
+        if( run_deep_plc ) {
+            for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+                lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
+            }
+            /* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
+            for( i = 0; i < psDec->frame_length; i++ ) {
+                sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
+            }
+        } else {
+          for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+              lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+          }
+        }
+    }
+#endif
+
+    /* Save LPC state */
+    silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+    /**************************************/
+    /* Update states                      */
+    /**************************************/
+    psPLC->rand_seed     = rand_seed;
+    psPLC->randScale_Q14 = rand_scale_Q14;
+    for( i = 0; i < MAX_NB_SUBFR; i++ ) {
+        psDecCtrl->pitchL[ i ] = lag;
+    }
+    RESTORE_STACK;
+}
+
+/* Glues concealed frames with new good received frames */
+void silk_PLC_glue_frames(
+    silk_decoder_state                  *psDec,             /* I/O decoder state        */
+    opus_int16                          frame[],            /* I/O signal               */
+    opus_int                            length              /* I length of signal       */
+)
+{
+    opus_int   i, energy_shift;
+    opus_int32 energy;
+    silk_PLC_struct *psPLC;
+    psPLC = &psDec->sPLC;
+
+    if( psDec->lossCnt ) {
+        /* Calculate energy in concealed residual */
+        silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
+
+        psPLC->last_frame_lost = 1;
+    } else {
+        if( psDec->sPLC.last_frame_lost ) {
+            /* Calculate residual in decoded signal if last frame was lost */
+            silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
+
+            /* Normalize energies */
+            if( energy_shift > psPLC->conc_energy_shift ) {
+                psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
+            } else if( energy_shift < psPLC->conc_energy_shift ) {
+                energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
+            }
+
+            /* Fade in the energy difference */
+            if( energy > psPLC->conc_energy ) {
+                opus_int32 frac_Q24, LZ;
+                opus_int32 gain_Q16, slope_Q16;
+
+                LZ = silk_CLZ32( psPLC->conc_energy );
+                LZ = LZ - 1;
+                psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
+                energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
+
+                frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
+
+                gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
+                slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
+                /* Make slope 4x steeper to avoid missing onsets after DTX */
+                slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
+#ifdef ENABLE_DEEP_PLC
+                if ( psDec->sPLC.fs_kHz != 16 )
+#endif
+                {
+                    for( i = 0; i < length; i++ ) {
+                        frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
+                        gain_Q16 += slope_Q16;
+                        if( gain_Q16 > (opus_int32)1 << 16 ) {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        psPLC->last_frame_lost = 0;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/PLC.h
new file mode 100644 (file)
index 0000000..7dffcc3
--- /dev/null
@@ -0,0 +1,64 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_PLC_H
+#define SILK_PLC_H
+
+#include "main.h"
+
+#define BWE_COEF                        0.99
+#define V_PITCH_GAIN_START_MIN_Q14      11469               /* 0.7 in Q14               */
+#define V_PITCH_GAIN_START_MAX_Q14      15565               /* 0.95 in Q14              */
+#define MAX_PITCH_LAG_MS                18
+#define RAND_BUF_SIZE                   128
+#define RAND_BUF_MASK                   ( RAND_BUF_SIZE - 1 )
+#define LOG2_INV_LPC_GAIN_HIGH_THRES    3                   /* 2^3 = 8 dB LPC gain      */
+#define LOG2_INV_LPC_GAIN_LOW_THRES     8                   /* 2^8 = 24 dB LPC gain     */
+#define PITCH_DRIFT_FAC_Q16             655                 /* 0.01 in Q16              */
+
+void silk_PLC_Reset(
+    silk_decoder_state                  *psDec              /* I/O Decoder state        */
+);
+
+void silk_PLC(
+    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
+    silk_decoder_control                *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                          frame[],            /* I/O  signal              */
+    opus_int                            lost,               /* I Loss flag              */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                      *lpcnet,
+#endif
+    int                                 arch                /* I Run-time architecture  */
+);
+
+void silk_PLC_glue_frames(
+    silk_decoder_state                  *psDec,             /* I/O decoder state        */
+    opus_int16                          frame[],            /* I/O signal               */
+    opus_int                            length              /* I length of signal       */
+);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX.h
new file mode 100644 (file)
index 0000000..053da9a
--- /dev/null
@@ -0,0 +1,641 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_SIGPROC_FIX_H
+#define SILK_SIGPROC_FIX_H
+
+
+/*#define silk_MACRO_COUNT */          /* Used to enable WMOPS counting */
+
+#define SILK_MAX_ORDER_LPC            24            /* max order of the LPC analysis in schur() and k2a() */
+
+#include <string.h>                                 /* for memset(), memcpy(), memmove() */
+#include "typedef.h"
+#include "resampler_structs.h"
+#include "macros.h"
+#include "cpu_support.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/SigProc_FIX_sse.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/biquad_alt_arm.h"
+#include "arm/LPC_inv_pred_gain_arm.h"
+#endif
+
+/********************************************************************/
+/*                    SIGNAL PROCESSING FUNCTIONS                   */
+/********************************************************************/
+
+/*!
+ * Initialize/reset the resampler state for a given pair of input/output sampling rates
+*/
+opus_int silk_resampler_init(
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int32                  Fs_Hz_in,           /* I    Input sampling rate (Hz)                                    */
+    opus_int32                  Fs_Hz_out,          /* I    Output sampling rate (Hz)                                   */
+    opus_int                    forEnc              /* I    If 1: encoder; if 0: decoder                                */
+);
+
+/*!
+ * Resampler: convert from one sampling rate to another
+ */
+opus_int silk_resampler(
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int16                  out[],              /* O    Output signal                                               */
+    const opus_int16            in[],               /* I    Input signal                                                */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+);
+
+/*!
+* Downsample 2x, mediocre quality
+*/
+void silk_resampler_down2(
+    opus_int32                  *S,                 /* I/O  State vector [ 2 ]                                          */
+    opus_int16                  *out,               /* O    Output signal [ len ]                                       */
+    const opus_int16            *in,                /* I    Input signal [ floor(len/2) ]                               */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+);
+
+/*!
+ * Downsample by a factor 2/3, low quality
+*/
+void silk_resampler_down2_3(
+    opus_int32                  *S,                 /* I/O  State vector [ 6 ]                                          */
+    opus_int16                  *out,               /* O    Output signal [ floor(2*inLen/3) ]                          */
+    const opus_int16            *in,                /* I    Input signal [ inLen ]                                      */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+);
+
+/*!
+ * second order ARMA filter;
+ * slower than biquad() but uses more precise coefficients
+ * can handle (slowly) varying coefficients
+ */
+void silk_biquad_alt_stride1(
+    const opus_int16            *in,                /* I     input signal                                               */
+    const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+    const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+    opus_int32                  *S,                 /* I/O   State vector [2]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+);
+
+void silk_biquad_alt_stride2_c(
+    const opus_int16            *in,                /* I     input signal                                               */
+    const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+    const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+    opus_int32                  *S,                 /* I/O   State vector [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+);
+
+/* Variable order MA prediction error filter. */
+void silk_LPC_analysis_filter(
+    opus_int16                  *out,               /* O    Output signal                                               */
+    const opus_int16            *in,                /* I    Input signal                                                */
+    const opus_int16            *B,                 /* I    MA prediction coefficients, Q12 [order]                     */
+    const opus_int32            len,                /* I    Signal length                                               */
+    const opus_int32            d,                  /* I    Filter order                                                */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+    opus_int16                  *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int              d,                  /* I    Length of ar                                                */
+    opus_int32                  chirp_Q16           /* I    Chirp factor (typically in the range 0 to 1)                */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander_32(
+    opus_int32                  *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int              d,                  /* I    Length of ar                                                */
+    opus_int32                  chirp_Q16           /* I    Chirp factor in Q16                                         */
+);
+
+/* Compute inverse of LPC prediction gain, and                           */
+/* test if LPC coefficients are stable (all poles within unit circle)    */
+opus_int32 silk_LPC_inverse_pred_gain_c(            /* O   Returns inverse prediction gain in energy domain, Q30        */
+    const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
+    const opus_int              order               /* I   Prediction order                                             */
+);
+
+/* Split signal in two decimated bands using first-order allpass filters */
+void silk_ana_filt_bank_1(
+    const opus_int16            *in,                /* I    Input signal [N]                                            */
+    opus_int32                  *S,                 /* I/O  State vector [2]                                            */
+    opus_int16                  *outL,              /* O    Low band [N/2]                                              */
+    opus_int16                  *outH,              /* O    High band [N/2]                                             */
+    const opus_int32            N                   /* I    Number of input samples                                     */
+);
+
+#if !defined(OVERRIDE_silk_biquad_alt_stride2)
+#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
+#endif
+
+#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+#define silk_LPC_inverse_pred_gain(A_Q12, order, arch)     ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
+#endif
+
+/********************************************************************/
+/*                        SCALAR FUNCTIONS                          */
+/********************************************************************/
+
+/* Approximation of 128 * log2() (exact inverse of approx 2^() below) */
+/* Convert input to a log scale    */
+opus_int32 silk_lin2log(
+    const opus_int32            inLin               /* I  input in linear scale                                         */
+);
+
+/* Approximation of a sigmoid function */
+opus_int silk_sigm_Q15(
+    opus_int                    in_Q5               /* I                                                                */
+);
+
+/* Approximation of 2^() (exact inverse of approx log2() above) */
+/* Convert input to a linear scale */
+opus_int32 silk_log2lin(
+    const opus_int32            inLog_Q7            /* I  input on log scale                                            */
+);
+
+/* Compute number of bits to right shift the sum of squares of a vector    */
+/* of int16s to make it fit in an int32                                    */
+void silk_sum_sqr_shift(
+    opus_int32                  *energy,            /* O   Energy of x, after shifting to the right                     */
+    opus_int                    *shift,             /* O   Number of bits right shift applied to energy                 */
+    const opus_int16            *x,                 /* I   Input vector                                                 */
+    opus_int                    len                 /* I   Length of input vector                                       */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence    */
+/* Faster than schur64(), but much less accurate.                          */
+/* uses SMLAWB(), requiring armv5E and higher.                             */
+opus_int32 silk_schur(                              /* O    Returns residual energy                                     */
+    opus_int16                  *rc_Q15,            /* O    reflection coefficients [order] Q15                         */
+    const opus_int32            *c,                 /* I    correlations [order+1]                                      */
+    const opus_int32            order               /* I    prediction order                                            */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence    */
+/* Slower than schur(), but more accurate.                                 */
+/* Uses SMULL(), available on armv4                                        */
+opus_int32 silk_schur64(                            /* O    returns residual energy                                     */
+    opus_int32                  rc_Q16[],           /* O    Reflection coefficients [order] Q16                         */
+    const opus_int32            c[],                /* I    Correlations [order+1]                                      */
+    opus_int32                  order               /* I    Prediction order                                            */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a(
+    opus_int32                  *A_Q24,             /* O    Prediction coefficients [order] Q24                         */
+    const opus_int16            *rc_Q15,            /* I    Reflection coefficients [order] Q15                         */
+    const opus_int32            order               /* I    Prediction order                                            */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a_Q16(
+    opus_int32                  *A_Q24,             /* O    Prediction coefficients [order] Q24                         */
+    const opus_int32            *rc_Q16,            /* I    Reflection coefficients [order] Q16                         */
+    const opus_int32            order               /* I    Prediction order                                            */
+);
+
+/* Apply sine window to signal vector.                              */
+/* Window types:                                                    */
+/*    1 -> sine window from 0 to pi/2                               */
+/*    2 -> sine window from pi/2 to pi                              */
+/* every other sample of window is linearly interpolated, for speed */
+void silk_apply_sine_window(
+    opus_int16                  px_win[],           /* O    Pointer to windowed signal                                  */
+    const opus_int16            px[],               /* I    Pointer to input signal                                     */
+    const opus_int              win_type,           /* I    Selects a window type                                       */
+    const opus_int              length              /* I    Window length, multiple of 4                                */
+);
+
+/* Compute autocorrelation */
+void silk_autocorr(
+    opus_int32                  *results,           /* O    Result (length correlationCount)                            */
+    opus_int                    *scale,             /* O    Scaling of the correlation vector                           */
+    const opus_int16            *inputData,         /* I    Input data to correlate                                     */
+    const opus_int              inputDataSize,      /* I    Length of input                                             */
+    const opus_int              correlationCount,   /* I    Number of correlation taps to compute                       */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+void silk_decode_pitch(
+    opus_int16                  lagIndex,           /* I                                                                */
+    opus_int8                   contourIndex,       /* O                                                                */
+    opus_int                    pitch_lags[],       /* O    4 pitch values                                              */
+    const opus_int              Fs_kHz,             /* I    sampling frequency (kHz)                                    */
+    const opus_int              nb_subfr            /* I    number of sub frames                                        */
+);
+
+opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0 voiced, 1 unvoiced                      */
+    const opus_int16            *frame,             /* I    Signal of length PE_FRAME_LENGTH_MS*Fs_kHz                  */
+    opus_int                    *pitch_out,         /* O    4 pitch lag values                                          */
+    opus_int16                  *lagIndex,          /* O    Lag Index                                                   */
+    opus_int8                   *contourIndex,      /* O    Pitch contour Index                                         */
+    opus_int                    *LTPCorr_Q15,       /* I/O  Normalized correlation; input: value from previous frame    */
+    opus_int                    prevLag,            /* I    Last lag of previous frame; set to zero is unvoiced         */
+    const opus_int32            search_thres1_Q16,  /* I    First stage threshold for lag candidates 0 - 1              */
+    const opus_int              search_thres2_Q13,  /* I    Final threshold for lag candidates 0 - 1                    */
+    const opus_int              Fs_kHz,             /* I    Sample frequency (kHz)                                      */
+    const opus_int              complexity,         /* I    Complexity setting, 0-2, where 2 is highest                 */
+    const opus_int              nb_subfr,           /* I    number of 5 ms subframes                                    */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
+void silk_A2NLSF(
+    opus_int16                  *NLSF,              /* O    Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
+    opus_int32                  *a_Q16,             /* I/O  Monic whitening filter coefficients in Q16 [d]              */
+    const opus_int              d                   /* I    Filter order (must be even)                                 */
+);
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+    opus_int16                  *a_Q12,             /* O    monic whitening filter coefficients in Q12,  [ d ]          */
+    const opus_int16            *NLSF,              /* I    normalized line spectral frequencies in Q15, [ d ]          */
+    const opus_int              d,                  /* I    filter order (should be even)                               */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                  *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
+);
+
+void silk_insertion_sort_increasing(
+    opus_int32                  *a,                 /* I/O   Unsorted / Sorted vector                                   */
+    opus_int                    *idx,               /* O     Index vector for the sorted elements                       */
+    const opus_int              L,                  /* I     Vector length                                              */
+    const opus_int              K                   /* I     Number of correctly sorted positions                       */
+);
+
+void silk_insertion_sort_decreasing_int16(
+    opus_int16                  *a,                 /* I/O   Unsorted / Sorted vector                                   */
+    opus_int                    *idx,               /* O     Index vector for the sorted elements                       */
+    const opus_int              L,                  /* I     Vector length                                              */
+    const opus_int              K                   /* I     Number of correctly sorted positions                       */
+);
+
+void silk_insertion_sort_increasing_all_values_int16(
+     opus_int16                 *a,                 /* I/O   Unsorted / Sorted vector                                   */
+     const opus_int             L                   /* I     Vector length                                              */
+);
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+          opus_int16            *NLSF_Q15,          /* I/O   Unstable/stabilized normalized LSF vector in Q15 [L]       */
+    const opus_int16            *NDeltaMin_Q15,     /* I     Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1]   */
+    const opus_int              L                   /* I     Number of NLSF parameters in the input vector              */
+);
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+    opus_int16                  *pNLSFW_Q_OUT,      /* O     Pointer to input vector weights [D]                        */
+    const opus_int16            *pNLSF_Q15,         /* I     Pointer to input vector         [D]                        */
+    const opus_int              D                   /* I     Input vector dimension (even)                              */
+);
+
+/* Compute reflection coefficients from input signal */
+void silk_burg_modified_c(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+/* Copy and multiply a vector by a constant */
+void silk_scale_copy_vector16(
+    opus_int16                  *data_out,
+    const opus_int16            *data_in,
+    opus_int32                  gain_Q16,           /* I    Gain in Q16                                                 */
+    const opus_int              dataSize            /* I    Length                                                      */
+);
+
+/* Some for the LTP related function requires Q26 to work.*/
+void silk_scale_vector32_Q26_lshift_18(
+    opus_int32                  *data1,             /* I/O  Q0/Q18                                                      */
+    opus_int32                  gain_Q26,           /* I    Q26                                                         */
+    opus_int                    dataSize            /* I    length                                                      */
+);
+
+/********************************************************************/
+/*                        INLINE ARM MATH                           */
+/********************************************************************/
+
+/*    return sum( inVec1[i] * inVec2[i] ) */
+
+opus_int32 silk_inner_prod_aligned(
+    const opus_int16 *const     inVec1,             /*    I input vector 1                                              */
+    const opus_int16 *const     inVec2,             /*    I input vector 2                                              */
+    const opus_int              len,                /*    I vector lengths                                              */
+    int                         arch                /*    I Run-time architecture                                       */
+);
+
+
+opus_int32 silk_inner_prod_aligned_scale(
+    const opus_int16 *const     inVec1,             /*    I input vector 1                                              */
+    const opus_int16 *const     inVec2,             /*    I input vector 2                                              */
+    const opus_int              scale,              /*    I number of bits to shift                                     */
+    const opus_int              len                 /*    I vector lengths                                              */
+);
+
+opus_int64 silk_inner_prod16_c(
+    const opus_int16            *inVec1,            /*    I input vector 1                                              */
+    const opus_int16            *inVec2,            /*    I input vector 2                                              */
+    const opus_int              len                 /*    I vector lengths                                              */
+);
+
+/********************************************************************/
+/*                                MACROS                            */
+/********************************************************************/
+
+/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
+   left. Output is 32bit int.
+   Note: contemporary compilers recognize the C expression below and
+   compile it into a 'ror' instruction if available. No need for OPUS_INLINE ASM! */
+static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
+{
+    opus_uint32 x = (opus_uint32) a32;
+    opus_uint32 r = (opus_uint32) rot;
+    opus_uint32 m = (opus_uint32) -rot;
+    if( rot == 0 ) {
+        return a32;
+    } else if( rot < 0 ) {
+        return (opus_int32) ((x << m) | (x >> (32 - m)));
+    } else {
+        return (opus_int32) ((x << (32 - r)) | (x >> r));
+    }
+}
+
+/* Allocate opus_int16 aligned to 4-byte memory address */
+#if EMBEDDED_ARM
+#define silk_DWORD_ALIGN __attribute__((aligned(4)))
+#else
+#define silk_DWORD_ALIGN
+#endif
+
+/* Useful Macros that can be adjusted to other platforms */
+#define silk_memcpy(dest, src, size)        memcpy((dest), (src), (size))
+#define silk_memset(dest, src, size)        memset((dest), (src), (size))
+#define silk_memmove(dest, src, size)       memmove((dest), (src), (size))
+
+/* Fixed point macros */
+
+/* (a32 * b32) output have to be 32bit int */
+#define silk_MUL(a32, b32)                  ((a32) * (b32))
+
+/* (a32 * b32) output have to be 32bit uint */
+#define silk_MUL_uint(a32, b32)             silk_MUL(a32, b32)
+
+/* a32 + (b32 * c32) output have to be 32bit int */
+#define silk_MLA(a32, b32, c32)             silk_ADD32((a32),((b32) * (c32)))
+
+/* a32 + (b32 * c32) output have to be 32bit uint */
+#define silk_MLA_uint(a32, b32, c32)        silk_MLA(a32, b32, c32)
+
+/* ((a32 >> 16)  * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMULTT(a32, b32)               (((a32) >> 16) * ((b32) >> 16))
+
+/* a32 + ((a32 >> 16)  * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMLATT(a32, b32, c32)          silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
+
+#define silk_SMLALBB(a64, b16, c16)         silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16)))
+
+/* (a32 * b32) */
+#define silk_SMULL(a32, b32)                ((opus_int64)(a32) * /*(opus_int64)*/(b32))
+
+/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+   (just standard two's complement implementation-specific behaviour) */
+#define silk_ADD32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
+/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+   (just standard two's complement implementation-specific behaviour) */
+#define silk_SUB32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
+
+/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
+#define silk_MLA_ovflw(a32, b32, c32)       silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
+#define silk_SMLABB_ovflw(a32, b32, c32)    (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))))
+
+#define silk_DIV32_16(a32, b16)             ((opus_int32)((a32) / (b16)))
+#define silk_DIV32(a32, b32)                ((opus_int32)((a32) / (b32)))
+
+/* These macros enables checking for overflow in silk_API_Debug.h*/
+#define silk_ADD16(a, b)                    ((a) + (b))
+#define silk_ADD32(a, b)                    ((a) + (b))
+#define silk_ADD64(a, b)                    ((a) + (b))
+
+#define silk_SUB16(a, b)                    ((a) - (b))
+#define silk_SUB32(a, b)                    ((a) - (b))
+#define silk_SUB64(a, b)                    ((a) - (b))
+
+#define silk_SAT8(a)                        ((a) > silk_int8_MAX ? silk_int8_MAX  :       \
+                                            ((a) < silk_int8_MIN ? silk_int8_MIN  : (a)))
+#define silk_SAT16(a)                       ((a) > silk_int16_MAX ? silk_int16_MAX :      \
+                                            ((a) < silk_int16_MIN ? silk_int16_MIN : (a)))
+#define silk_SAT32(a)                       ((a) > silk_int32_MAX ? silk_int32_MAX :      \
+                                            ((a) < silk_int32_MIN ? silk_int32_MIN : (a)))
+
+#define silk_CHECK_FIT8(a)                  (a)
+#define silk_CHECK_FIT16(a)                 (a)
+#define silk_CHECK_FIT32(a)                 (a)
+
+#define silk_ADD_SAT16(a, b)                (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) )
+#define silk_ADD_SAT64(a, b)                ((((a) + (b)) & 0x8000000000000000LL) == 0 ?                            \
+                                            ((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) : \
+                                            ((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) )
+
+#define silk_SUB_SAT16(a, b)                (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) )
+#define silk_SUB_SAT64(a, b)                ((((a)-(b)) & 0x8000000000000000LL) == 0 ?                                               \
+                                            (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) : \
+                                            ((((a)^0x8000000000000000LL) & (b)  & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) )
+
+/* Saturation for positive input values */
+#define silk_POS_SAT32(a)                   ((a) > silk_int32_MAX ? silk_int32_MAX : (a))
+
+/* Add with saturation for positive input values */
+#define silk_ADD_POS_SAT8(a, b)             ((((a)+(b)) & 0x80)                 ? silk_int8_MAX  : ((a)+(b)))
+#define silk_ADD_POS_SAT16(a, b)            ((((a)+(b)) & 0x8000)               ? silk_int16_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b)            ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
+
+#define silk_LSHIFT8(a, shift)              ((opus_int8)((opus_uint8)(a)<<(shift)))         /* shift >= 0, shift < 8  */
+#define silk_LSHIFT16(a, shift)             ((opus_int16)((opus_uint16)(a)<<(shift)))       /* shift >= 0, shift < 16 */
+#define silk_LSHIFT32(a, shift)             ((opus_int32)((opus_uint32)(a)<<(shift)))       /* shift >= 0, shift < 32 */
+#define silk_LSHIFT64(a, shift)             ((opus_int64)((opus_uint64)(a)<<(shift)))       /* shift >= 0, shift < 64 */
+#define silk_LSHIFT(a, shift)               silk_LSHIFT32(a, shift)                         /* shift >= 0, shift < 32 */
+
+#define silk_RSHIFT8(a, shift)              ((a)>>(shift))                                  /* shift >= 0, shift < 8  */
+#define silk_RSHIFT16(a, shift)             ((a)>>(shift))                                  /* shift >= 0, shift < 16 */
+#define silk_RSHIFT32(a, shift)             ((a)>>(shift))                                  /* shift >= 0, shift < 32 */
+#define silk_RSHIFT64(a, shift)             ((a)>>(shift))                                  /* shift >= 0, shift < 64 */
+#define silk_RSHIFT(a, shift)               silk_RSHIFT32(a, shift)                         /* shift >= 0, shift < 32 */
+
+/* saturates before shifting */
+#define silk_LSHIFT_SAT32(a, shift)         (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \
+                                                    silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
+
+#define silk_LSHIFT_ovflw(a, shift)         ((opus_int32)((opus_uint32)(a) << (shift)))     /* shift >= 0, allowed to overflow */
+#define silk_LSHIFT_uint(a, shift)          ((a) << (shift))                                /* shift >= 0 */
+#define silk_RSHIFT_uint(a, shift)          ((a) >> (shift))                                /* shift >= 0 */
+
+#define silk_ADD_LSHIFT(a, b, shift)        ((a) + silk_LSHIFT((b), (shift)))               /* shift >= 0 */
+#define silk_ADD_LSHIFT32(a, b, shift)      silk_ADD32((a), silk_LSHIFT32((b), (shift)))    /* shift >= 0 */
+#define silk_ADD_LSHIFT_uint(a, b, shift)   ((a) + silk_LSHIFT_uint((b), (shift)))          /* shift >= 0 */
+#define silk_ADD_RSHIFT(a, b, shift)        ((a) + silk_RSHIFT((b), (shift)))               /* shift >= 0 */
+#define silk_ADD_RSHIFT32(a, b, shift)      silk_ADD32((a), silk_RSHIFT32((b), (shift)))    /* shift >= 0 */
+#define silk_ADD_RSHIFT_uint(a, b, shift)   ((a) + silk_RSHIFT_uint((b), (shift)))          /* shift >= 0 */
+#define silk_SUB_LSHIFT32(a, b, shift)      silk_SUB32((a), silk_LSHIFT32((b), (shift)))    /* shift >= 0 */
+#define silk_SUB_RSHIFT32(a, b, shift)      silk_SUB32((a), silk_RSHIFT32((b), (shift)))    /* shift >= 0 */
+
+/* Requires that shift > 0 */
+#define silk_RSHIFT_ROUND(a, shift)         ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+#define silk_RSHIFT_ROUND64(a, shift)       ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+
+/* Number of rightshift required to fit the multiplication */
+#define silk_NSHIFT_MUL_32_32(a, b)         ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) )
+#define silk_NSHIFT_MUL_16_16(a, b)         ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) )
+
+
+#define silk_min(a, b)                      (((a) < (b)) ? (a) : (b))
+#define silk_max(a, b)                      (((a) > (b)) ? (a) : (b))
+
+/* Macro to convert floating-point constants to fixed-point */
+#define SILK_FIX_CONST( C, Q )              ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
+
+/* silk_min() versions with typecast in the function call */
+static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+
+#define silk_LIMIT( a, limit1, limit2)      ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+                                                                 : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
+
+#define silk_LIMIT_int                      silk_LIMIT
+#define silk_LIMIT_16                       silk_LIMIT
+#define silk_LIMIT_32                       silk_LIMIT
+
+#define silk_abs(a)                         (((a) >  0)  ? (a) : -(a))            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+#define silk_abs_int(a)                     (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
+#define silk_abs_int32(a)                   (((a) ^ ((a) >> 31)) - ((a) >> 31))
+#define silk_abs_int64(a)                   (((a) >  0)  ? (a) : -(a))
+
+#define silk_sign(a)                        ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
+
+/* PSEUDO-RANDOM GENERATOR                                                          */
+/* Make sure to store the result as the seed for the next call (also in between     */
+/* frames), otherwise result won't be random at all. When only using some of the    */
+/* bits, take the most significant bits by right-shifting.                          */
+#define RAND_MULTIPLIER                     196314165
+#define RAND_INCREMENT                      907633515
+#define silk_RAND(seed)                     (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
+
+/*  Add some multiplication functions that can be easily mapped to ARM/MIPS32. */
+
+/*    silk_SMMUL: Signed top word multiply.
+          ARMv6        2 instruction cycles.
+          ARMv3M+      3 instruction cycles. use SMULL and ignore LSB registers.(except xM)
+          MIPS32       2 instructions mul+mfhi
+          MIPS32r6     1 instruction muh */
+/*#define silk_SMMUL(a32, b32)                (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/
+/* the following seems faster on x86 */
+#define silk_SMMUL(a32, b32)                (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
+
+#if !defined(OVERRIDE_silk_burg_modified)
+#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+    ((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+#endif
+
+#if !defined(OVERRIDE_silk_inner_prod16)
+#define silk_inner_prod16(inVec1, inVec2, len, arch) \
+    ((void)(arch),silk_inner_prod16_c(inVec1, inVec2, len))
+#endif
+
+#include "Inlines.h"
+#include "MacroCount.h"
+#include "MacroDebug.h"
+
+#ifdef OPUS_ARM_INLINE_ASM
+#include "arm/SigProc_FIX_armv4.h"
+#endif
+
+#ifdef OPUS_ARM_INLINE_EDSP
+#include "arm/SigProc_FIX_armv5e.h"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips_dsp) && __mips == 32
+#include "mips/sigproc_fix_mipsr1.h"
+#endif
+
+#ifdef OPUS_XTENSA_LX7
+#include "xtensa/SigProc_FIX_lx7.h"
+#endif
+
+
+#endif /* SILK_SIGPROC_FIX_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv4.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv4.h
new file mode 100644 (file)
index 0000000..ff62b1e
--- /dev/null
@@ -0,0 +1,47 @@
+/***********************************************************************
+Copyright (C) 2013 Xiph.Org Foundation and contributors
+Copyright (c) 2013       Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_SIGPROC_FIX_ARMv4_H
+#define SILK_SIGPROC_FIX_ARMv4_H
+
+#undef silk_MLA
+static OPUS_INLINE opus_int32 silk_MLA_armv4(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  opus_int32 res;
+  __asm__(
+      "#silk_MLA\n\t"
+      "mla %0, %1, %2, %3\n\t"
+      : "=&r"(res)
+      : "r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_MLA(a, b, c) (silk_MLA_armv4(a, b, c))
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv5e.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_armv5e.h
new file mode 100644 (file)
index 0000000..617a09c
--- /dev/null
@@ -0,0 +1,61 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (c) 2013       Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_SIGPROC_FIX_ARMv5E_H
+#define SILK_SIGPROC_FIX_ARMv5E_H
+
+#undef silk_SMULTT
+static OPUS_INLINE opus_int32 silk_SMULTT_armv5e(opus_int32 a, opus_int32 b)
+{
+  opus_int32 res;
+  __asm__(
+      "#silk_SMULTT\n\t"
+      "smultt %0, %1, %2\n\t"
+      : "=r"(res)
+      : "%r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SMULTT(a, b) (silk_SMULTT_armv5e(a, b))
+
+#undef silk_SMLATT
+static OPUS_INLINE opus_int32 silk_SMLATT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  opus_int32 res;
+  __asm__(
+      "#silk_SMLATT\n\t"
+      "smlatt %0, %1, %2, %3\n\t"
+      : "=r"(res)
+      : "%r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_SMLATT(a, b, c) (silk_SMLATT_armv5e(a, b, c))
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FIX_sse.h
new file mode 100644 (file)
index 0000000..89a5ec8
--- /dev/null
@@ -0,0 +1,99 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SIGPROC_FIX_SSE_H
+# define SIGPROC_FIX_SSE_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+void silk_burg_modified_sse4_1(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_burg_modified
+#   define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+       ((void)(arch), silk_burg_modified_sse4_1(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */);
+
+#   define OVERRIDE_silk_burg_modified
+#   define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+     ((*SILK_BURG_MODIFIED_IMPL[(arch) & OPUS_ARCHMASK])(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+#  endif
+
+opus_int64 silk_inner_prod16_sse4_1(
+    const opus_int16 *inVec1,
+    const opus_int16 *inVec2,
+    const opus_int   len
+);
+
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_inner_prod16
+#   define silk_inner_prod16(inVec1, inVec2, len, arch) \
+       ((void)(arch),silk_inner_prod16_sse4_1(inVec1, inVec2, len))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int64 (*const SILK_INNER_PROD16_IMPL[OPUS_ARCHMASK + 1])(
+                    const opus_int16 *inVec1,
+                    const opus_int16 *inVec2,
+                    const opus_int   len);
+
+#   define OVERRIDE_silk_inner_prod16
+#   define silk_inner_prod16(inVec1, inVec2, len, arch) \
+     ((*SILK_INNER_PROD16_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
+
+#  endif
+# endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FLP.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/SigProc_FLP.h
new file mode 100644 (file)
index 0000000..783099b
--- /dev/null
@@ -0,0 +1,197 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_SIGPROC_FLP_H
+#define SILK_SIGPROC_FLP_H
+
+#include "SigProc_FIX.h"
+#include "float_cast.h"
+#include "main.h"
+#include <math.h>
+
+
+/********************************************************************/
+/*                    SIGNAL PROCESSING FUNCTIONS                   */
+/********************************************************************/
+
+/* Chirp (bw expand) LP AR filter */
+void silk_bwexpander_FLP(
+    silk_float          *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int      d,                  /* I    length of ar                                                */
+    const silk_float    chirp               /* I    chirp factor (typically in range (0..1) )                   */
+);
+
+/* compute inverse of LPC prediction gain, and                          */
+/* test if LPC coefficients are stable (all poles within unit circle)   */
+/* this code is based on silk_FLP_a2k()                                 */
+silk_float silk_LPC_inverse_pred_gain_FLP(  /* O    return inverse prediction gain, energy domain               */
+    const silk_float    *A,                 /* I    prediction coefficients [order]                             */
+    opus_int32          order               /* I    prediction order                                            */
+);
+
+silk_float silk_schur_FLP(                  /* O    returns residual energy                                     */
+    silk_float          refl_coef[],        /* O    reflection coefficients (length order)                      */
+    const silk_float    auto_corr[],        /* I    autocorrelation sequence (length order+1)                   */
+    opus_int            order               /* I    order                                                       */
+);
+
+void silk_k2a_FLP(
+    silk_float          *A,                 /* O     prediction coefficients [order]                            */
+    const silk_float    *rc,                /* I     reflection coefficients [order]                            */
+    opus_int32          order               /* I     prediction order                                           */
+);
+
+/* compute autocorrelation */
+void silk_autocorrelation_FLP(
+    silk_float          *results,           /* O    result (length correlationCount)                            */
+    const silk_float    *inputData,         /* I    input data to correlate                                     */
+    opus_int            inputDataSize,      /* I    length of input                                             */
+    opus_int            correlationCount,    /* I    number of correlation taps to compute                       */
+    int                 arch
+);
+
+opus_int silk_pitch_analysis_core_FLP(      /* O    Voicing estimate: 0 voiced, 1 unvoiced                      */
+    const silk_float    *frame,             /* I    Signal of length PE_FRAME_LENGTH_MS*Fs_kHz                  */
+    opus_int            *pitch_out,         /* O    Pitch lag values [nb_subfr]                                 */
+    opus_int16          *lagIndex,          /* O    Lag Index                                                   */
+    opus_int8           *contourIndex,      /* O    Pitch contour Index                                         */
+    silk_float          *LTPCorr,           /* I/O  Normalized correlation; input: value from previous frame    */
+    opus_int            prevLag,            /* I    Last lag of previous frame; set to zero is unvoiced         */
+    const silk_float    search_thres1,      /* I    First stage threshold for lag candidates 0 - 1              */
+    const silk_float    search_thres2,      /* I    Final threshold for lag candidates 0 - 1                    */
+    const opus_int      Fs_kHz,             /* I    sample frequency (kHz)                                      */
+    const opus_int      complexity,         /* I    Complexity setting, 0-2, where 2 is highest                 */
+    const opus_int      nb_subfr,           /* I    Number of 5 ms subframes                                    */
+    int                 arch                /* I    Run-time architecture                                       */
+);
+
+void silk_insertion_sort_decreasing_FLP(
+    silk_float          *a,                 /* I/O  Unsorted / Sorted vector                                    */
+    opus_int            *idx,               /* O    Index vector for the sorted elements                        */
+    const opus_int      L,                  /* I    Vector length                                               */
+    const opus_int      K                   /* I    Number of correctly sorted positions                        */
+);
+
+/* Compute reflection coefficients from input signal */
+silk_float silk_burg_modified_FLP(          /* O    returns residual energy                                     */
+    silk_float          A[],                /* O    prediction coefficients (length order)                      */
+    const silk_float    x[],                /* I    input signal, length: nb_subfr*(D+L_sub)                    */
+    const silk_float    minInvGain,         /* I    minimum inverse prediction gain                             */
+    const opus_int      subfr_length,       /* I    input signal subframe length (incl. D preceding samples)    */
+    const opus_int      nb_subfr,           /* I    number of subframes stacked in x                            */
+    const opus_int      D,                  /* I    order                                                       */
+    int                 arch
+);
+
+/* multiply a vector by a constant */
+void silk_scale_vector_FLP(
+    silk_float          *data1,
+    silk_float          gain,
+    opus_int            dataSize
+);
+
+/* copy and multiply a vector by a constant */
+void silk_scale_copy_vector_FLP(
+    silk_float          *data_out,
+    const silk_float    *data_in,
+    silk_float          gain,
+    opus_int            dataSize
+);
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_c(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+);
+
+#ifndef OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_c(data1, data2, dataSize))
+#endif
+
+
+/* sum of squares of a silk_float array, with result as double */
+double silk_energy_FLP(
+    const silk_float    *data,
+    opus_int            dataSize
+);
+
+/********************************************************************/
+/*                                MACROS                            */
+/********************************************************************/
+
+#define PI              (3.1415926536f)
+
+#define silk_min_float( a, b )                  (((a) < (b)) ? (a) :  (b))
+#define silk_max_float( a, b )                  (((a) > (b)) ? (a) :  (b))
+#define silk_abs_float( a )                     ((silk_float)fabs(a))
+
+/* sigmoid function */
+static OPUS_INLINE silk_float silk_sigmoid( silk_float x )
+{
+    return (silk_float)(1.0 / (1.0 + exp(-x)));
+}
+
+/* floating-point to integer conversion (rounding) */
+static OPUS_INLINE opus_int32 silk_float2int( silk_float x )
+{
+    return (opus_int32)float2int( x );
+}
+
+/* floating-point to integer conversion (rounding) */
+static OPUS_INLINE void silk_float2short_array(
+    opus_int16       *out,
+    const silk_float *in,
+    opus_int32       length
+)
+{
+    opus_int32 k;
+    for( k = length - 1; k >= 0; k-- ) {
+        out[k] = silk_SAT16( (opus_int32)float2int( in[k] ) );
+    }
+}
+
+/* integer to floating-point conversion */
+static OPUS_INLINE void silk_short2float_array(
+    silk_float       *out,
+    const opus_int16 *in,
+    opus_int32       length
+)
+{
+    opus_int32 k;
+    for( k = length - 1; k >= 0; k-- ) {
+        out[k] = (silk_float)in[k];
+    }
+}
+
+/* using log2() helps the fixed-point conversion */
+static OPUS_INLINE silk_float silk_log2( double x )
+{
+    return ( silk_float )( 3.32192809488736 * log10( x ) );
+}
+
+#endif /* SILK_SIGPROC_FLP_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt.c
new file mode 100644 (file)
index 0000000..54566a4
--- /dev/null
@@ -0,0 +1,121 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/*                                                                      *
+ * silk_biquad_alt.c                                              *
+ *                                                                      *
+ * Second order ARMA filter                                             *
+ * Can handle slowly varying filter coefficients                        *
+ *                                                                      */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Second order ARMA filter, alternative implementation */
+void silk_biquad_alt_stride1(
+    const opus_int16            *in,                /* I     input signal                                               */
+    const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+    const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+    opus_int32                  *S,                 /* I/O   State vector [2]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+)
+{
+    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+    opus_int   k;
+    opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
+
+    /* Negate A_Q28 values and split in two parts */
+    A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF;        /* lower part */
+    A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 );      /* upper part */
+    A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF;        /* lower part */
+    A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 );      /* upper part */
+
+    for( k = 0; k < len; k++ ) {
+        /* S[ 0 ], S[ 1 ]: Q12 */
+        inval = in[ k ];
+        out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
+
+        S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
+
+        S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
+
+        /* Scale back to Q0 and saturate */
+        out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
+    }
+}
+
+void silk_biquad_alt_stride2_c(
+    const opus_int16            *in,                /* I     input signal                                               */
+    const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+    const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+    opus_int32                  *S,                 /* I/O   State vector [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+)
+{
+    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+    opus_int   k;
+    opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
+
+    /* Negate A_Q28 values and split in two parts */
+    A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF;        /* lower part */
+    A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 );      /* upper part */
+    A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF;        /* lower part */
+    A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 );      /* upper part */
+
+    for( k = 0; k < len; k++ ) {
+        /* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
+        out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
+        out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
+
+        S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
+        S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
+        S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
+        S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
+
+        S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
+        S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
+        S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
+        S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
+
+        /* Scale back to Q0 and saturate */
+        out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
+        out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt_arm.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/biquad_alt_arm.h
new file mode 100644 (file)
index 0000000..66ea9f4
--- /dev/null
@@ -0,0 +1,68 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_BIQUAD_ALT_ARM_H
+# define SILK_BIQUAD_ALT_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_biquad_alt_stride2_neon(
+    const opus_int16            *in,                /* I     input signal                                               */
+    const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+    const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+    opus_int32                  *S,                 /* I/O   State vector [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_biquad_alt_stride2                   (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_silk_biquad_alt_stride2)
+/*Is run-time CPU detection enabled on this platform?*/
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
+        const opus_int16            *in,                /* I     input signal                                               */
+        const opus_int32            *B_Q28,             /* I     MA coefficients [3]                                        */
+        const opus_int32            *A_Q28,             /* I     AR coefficients [2]                                        */
+        opus_int32                  *S,                 /* I/O   State vector [4]                                           */
+        opus_int16                  *out,               /* O     output signal                                              */
+        const opus_int32            len                 /* I     signal length (must be even)                               */
+    );
+#   define OVERRIDE_silk_biquad_alt_stride2                  (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_silk_biquad_alt_stride2                  (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
+#  endif
+# endif
+
+#endif /* end SILK_BIQUAD_ALT_ARM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander.c
new file mode 100644 (file)
index 0000000..afa9790
--- /dev/null
@@ -0,0 +1,51 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+    opus_int16                  *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int              d,                  /* I    Length of ar                                                */
+    opus_int32                  chirp_Q16           /* I    Chirp factor (typically in the range 0 to 1)                */
+)
+{
+    opus_int   i;
+    opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+    /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below.  */
+    /* Bias in silk_SMULWB can lead to unstable filters                                */
+    for( i = 0; i < d - 1; i++ ) {
+        ar[ i ]    = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ]             ), 16 );
+        chirp_Q16 +=             silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+    }
+    ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander_32.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/bwexpander_32.c
new file mode 100644 (file)
index 0000000..1b37d96
--- /dev/null
@@ -0,0 +1,50 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter.
+   This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
+void silk_bwexpander_32(
+    opus_int32                  *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int              d,                  /* I    Length of ar                                                */
+    opus_int32                  chirp_Q16           /* I    Chirp factor in Q16                                         */
+)
+{
+    opus_int   i;
+    opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+    for( i = 0; i < d - 1; i++ ) {
+        ar[ i ]    = silk_SMULWW( chirp_Q16, ar[ i ] );
+        chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+    }
+    ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/code_signs.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/code_signs.c
new file mode 100644 (file)
index 0000000..dfd1dca
--- /dev/null
@@ -0,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*#define silk_enc_map(a)                ((a) > 0 ? 1 : 0)*/
+/*#define silk_dec_map(a)                ((a) > 0 ? 1 : -1)*/
+/* shifting avoids if-statement */
+#define silk_enc_map(a)                  ( silk_RSHIFT( (a), 15 ) + 1 )
+#define silk_dec_map(a)                  ( silk_LSHIFT( (a),  1 ) - 1 )
+
+/* Encodes signs of excitation */
+void silk_encode_signs(
+    ec_enc                      *psRangeEnc,                        /* I/O  Compressor data structure                   */
+    const opus_int8             pulses[],                           /* I    pulse signal                                */
+    opus_int                    length,                             /* I    length of input                             */
+    const opus_int              signalType,                         /* I    Signal type                                 */
+    const opus_int              quantOffsetType,                    /* I    Quantization offset type                    */
+    const opus_int              sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
+)
+{
+    opus_int         i, j, p;
+    opus_uint8       icdf[ 2 ];
+    const opus_int8  *q_ptr;
+    const opus_uint8 *icdf_ptr;
+
+    icdf[ 1 ] = 0;
+    q_ptr = pulses;
+    i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+    icdf_ptr = &silk_sign_iCDF[ i ];
+    length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    for( i = 0; i < length; i++ ) {
+        p = sum_pulses[ i ];
+        if( p > 0 ) {
+            icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
+            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+                if( q_ptr[ j ] != 0 ) {
+                    ec_enc_icdf( psRangeEnc, silk_enc_map( q_ptr[ j ]), icdf, 8 );
+                }
+            }
+        }
+        q_ptr += SHELL_CODEC_FRAME_LENGTH;
+    }
+}
+
+/* Decodes signs of excitation */
+void silk_decode_signs(
+    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure                   */
+    opus_int16                  pulses[],                           /* I/O  pulse signal                                */
+    opus_int                    length,                             /* I    length of input                             */
+    const opus_int              signalType,                         /* I    Signal type                                 */
+    const opus_int              quantOffsetType,                    /* I    Quantization offset type                    */
+    const opus_int              sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
+)
+{
+    opus_int         i, j, p;
+    opus_uint8       icdf[ 2 ];
+    opus_int16       *q_ptr;
+    const opus_uint8 *icdf_ptr;
+
+    icdf[ 1 ] = 0;
+    q_ptr = pulses;
+    i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+    icdf_ptr = &silk_sign_iCDF[ i ];
+    length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    for( i = 0; i < length; i++ ) {
+        p = sum_pulses[ i ];
+        if( p > 0 ) {
+            icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
+            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+                if( q_ptr[ j ] > 0 ) {
+                    /* attach sign */
+#if 0
+                    /* conditional implementation */
+                    if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) {
+                        q_ptr[ j ] = -q_ptr[ j ];
+                    }
+#else
+                    /* implementation with shift, subtraction, multiplication */
+                    q_ptr[ j ] *= silk_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) );
+#endif
+                }
+            }
+        }
+        q_ptr += SHELL_CODEC_FRAME_LENGTH;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/control.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/control.h
new file mode 100644 (file)
index 0000000..1a06cbe
--- /dev/null
@@ -0,0 +1,164 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_CONTROL_H
+#define SILK_CONTROL_H
+
+#include "typedef.h"
+
+
+/* Decoder API flags */
+#define FLAG_DECODE_NORMAL                      0
+#define FLAG_PACKET_LOST                        1
+#define FLAG_DECODE_LBRR                        2
+
+/***********************************************/
+/* Structure for controlling encoder operation */
+/***********************************************/
+typedef struct {
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsAPI;
+
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsInternal;
+
+    /* I:   Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000   */
+    opus_int32 API_sampleRate;
+
+    /* I:   Maximum internal sampling rate in Hertz; 8000/12000/16000                       */
+    opus_int32 maxInternalSampleRate;
+
+    /* I:   Minimum internal sampling rate in Hertz; 8000/12000/16000                       */
+    opus_int32 minInternalSampleRate;
+
+    /* I:   Soft request for internal sampling rate in Hertz; 8000/12000/16000              */
+    opus_int32 desiredInternalSampleRate;
+
+    /* I:   Number of samples per packet in milliseconds; 10/20/40/60                       */
+    opus_int payloadSize_ms;
+
+    /* I:   Bitrate during active speech in bits/second; internally limited                 */
+    opus_int32 bitRate;
+
+    /* I:   Uplink packet loss in percent (0-100)                                           */
+    opus_int packetLossPercentage;
+
+    /* I:   Complexity mode; 0 is lowest, 10 is highest complexity                          */
+    opus_int complexity;
+
+    /* I:   Flag to enable in-band Forward Error Correction (FEC); 0/1                      */
+    opus_int useInBandFEC;
+
+    /* I:   Flag to enable in-band Deep REDundancy (DRED); 0/1                              */
+    opus_int useDRED;
+
+    /* I:   Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
+    opus_int LBRR_coded;
+
+    /* I:   Flag to enable discontinuous transmission (DTX); 0/1                            */
+    opus_int useDTX;
+
+    /* I:   Flag to use constant bitrate                                                    */
+    opus_int useCBR;
+
+    /* I:   Maximum number of bits allowed for the frame                                    */
+    opus_int maxBits;
+
+    /* I:   Causes a smooth downmix to mono                                                 */
+    opus_int toMono;
+
+    /* I:   Opus encoder is allowing us to switch bandwidth                                 */
+    opus_int opusCanSwitch;
+
+    /* I: Make frames as independent as possible (but still use LPC)                        */
+    opus_int reducedDependency;
+
+    /* O:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */
+    opus_int32 internalSampleRate;
+
+    /* O: Flag that bandwidth switching is allowed (because low voice activity)             */
+    opus_int allowBandwidthSwitch;
+
+    /* O:   Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */
+    opus_int inWBmodeWithoutVariableLP;
+
+    /* O:   Stereo width */
+    opus_int stereoWidth_Q14;
+
+    /* O:   Tells the Opus encoder we're ready to switch                                    */
+    opus_int switchReady;
+
+    /* O: SILK Signal type */
+    opus_int signalType;
+
+    /* O: SILK offset (dithering) */
+    opus_int offset;
+} silk_EncControlStruct;
+
+/**************************************************************************/
+/* Structure for controlling decoder operation and reading decoder status */
+/**************************************************************************/
+typedef struct {
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsAPI;
+
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsInternal;
+
+    /* I:   Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000  */
+    opus_int32 API_sampleRate;
+
+    /* I:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */
+    opus_int32 internalSampleRate;
+
+    /* I:   Number of samples per packet in milliseconds; 10/20/40/60                       */
+    opus_int payloadSize_ms;
+
+    /* O:   Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz      */
+    opus_int prevPitchLag;
+
+    /* I:   Enable Deep PLC                                                                 */
+    opus_int enable_deep_plc;
+
+#ifdef ENABLE_OSCE
+    /* I: OSCE method */
+    opus_int osce_method;
+
+#ifdef ENABLE_OSCE_BWE
+    /* I: OSCE bandwidth extension method */
+    opus_int enable_osce_bwe;
+
+    /* I: extended mode */
+    opus_int osce_extended_mode;
+
+    /* O: previous extended mode */
+    opus_int prev_osce_extended_mode;
+#endif
+#endif
+} silk_DecControlStruct;
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/debug.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/debug.h
new file mode 100644 (file)
index 0000000..68190f5
--- /dev/null
@@ -0,0 +1,259 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_DEBUG_H
+#define SILK_DEBUG_H
+
+/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
+ * intermediate signals from the codec.
+ */
+#define SILK_DEBUG 0
+
+/* Flag for using timers */
+#define SILK_TIC_TOC 0
+
+#if SILK_DEBUG || SILK_TIC_TOC
+#include "typedef.h"
+#include <string.h>     /* strcpy, strcmp */
+#include <stdio.h>      /* file writing */
+#endif
+
+
+#if SILK_TIC_TOC
+
+unsigned long GetHighResolutionTime(void); /* O  time in usec*/
+
+#if (defined(_WIN32) || defined(_WINCE))
+#include <windows.h>    /* timer */
+#else   /* Linux or Mac*/
+#include <sys/time.h>
+#endif
+
+/*********************************/
+/* timer functions for profiling */
+/*********************************/
+/* example:                                                         */
+/*                                                                  */
+/* TIC(LPC)                                                         */
+/* do_LPC(in_vec, order, acoef);    // do LPC analysis              */
+/* TOC(LPC)                                                         */
+/*                                                                  */
+/* and call the following just before exiting (from main)           */
+/*                                                                  */
+/* silk_TimerSave("silk_TimingData.txt");                           */
+/*                                                                  */
+/* results are now in silk_TimingData.txt                           */
+
+void silk_TimerSave(char *file_name);
+
+/* max number of timers (in different locations) */
+#define silk_NUM_TIMERS_MAX                  50
+/* max length of name tags in TIC(..), TOC(..) */
+#define silk_NUM_TIMERS_MAX_TAG_LEN          30
+
+extern int           silk_Timer_nTimers;
+extern int           silk_Timer_depth_ctr;
+extern char          silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
+#ifdef _WIN32
+extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
+#else
+extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
+#endif
+extern unsigned int  silk_Timer_cnt[silk_NUM_TIMERS_MAX];
+extern opus_int64    silk_Timer_sum[silk_NUM_TIMERS_MAX];
+extern opus_int64    silk_Timer_max[silk_NUM_TIMERS_MAX];
+extern opus_int64    silk_Timer_min[silk_NUM_TIMERS_MAX];
+extern opus_int64    silk_Timer_depth[silk_NUM_TIMERS_MAX];
+
+/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */
+#ifdef _WIN32
+#define TIC(TAG_NAME) {                                     \
+    static int init = 0;                                    \
+    static int ID = -1;                                     \
+    if( init == 0 )                                         \
+    {                                                       \
+        int k;                                              \
+        init = 1;                                           \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {         \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
+                ID = k;                                     \
+                break;                                      \
+            }                                               \
+        }                                                   \
+        if (ID == -1) {                                     \
+            ID = silk_Timer_nTimers;                        \
+            silk_Timer_nTimers++;                           \
+            silk_Timer_depth[ID] = silk_Timer_depth_ctr;    \
+            strcpy(silk_Timer_tags[ID], #TAG_NAME);         \
+            silk_Timer_cnt[ID] = 0;                         \
+            silk_Timer_sum[ID] = 0;                         \
+            silk_Timer_min[ID] = 0xFFFFFFFF;                \
+            silk_Timer_max[ID] = 0;                         \
+        }                                                   \
+    }                                                       \
+    silk_Timer_depth_ctr++;                                 \
+    QueryPerformanceCounter(&silk_Timer_start[ID]);         \
+}
+#else
+#define TIC(TAG_NAME) {                                     \
+    static int init = 0;                                    \
+    static int ID = -1;                                     \
+    if( init == 0 )                                         \
+    {                                                       \
+        int k;                                              \
+        init = 1;                                           \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {         \
+        if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {  \
+                ID = k;                                     \
+                break;                                      \
+            }                                               \
+        }                                                   \
+        if (ID == -1) {                                     \
+            ID = silk_Timer_nTimers;                        \
+            silk_Timer_nTimers++;                           \
+            silk_Timer_depth[ID] = silk_Timer_depth_ctr;    \
+            strcpy(silk_Timer_tags[ID], #TAG_NAME);         \
+            silk_Timer_cnt[ID] = 0;                         \
+            silk_Timer_sum[ID] = 0;                         \
+            silk_Timer_min[ID] = 0xFFFFFFFF;                \
+            silk_Timer_max[ID] = 0;                         \
+        }                                                   \
+    }                                                       \
+    silk_Timer_depth_ctr++;                                 \
+    silk_Timer_start[ID] = GetHighResolutionTime();         \
+}
+#endif
+
+#ifdef _WIN32
+#define TOC(TAG_NAME) {                                             \
+    LARGE_INTEGER lpPerformanceCount;                               \
+    static int init = 0;                                            \
+    static int ID = 0;                                              \
+    if( init == 0 )                                                 \
+    {                                                               \
+        int k;                                                      \
+        init = 1;                                                   \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {                 \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {      \
+                ID = k;                                             \
+                break;                                              \
+            }                                                       \
+        }                                                           \
+    }                                                               \
+    QueryPerformanceCounter(&lpPerformanceCount);                   \
+    lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart;   \
+    if((lpPerformanceCount.QuadPart < 100000000) &&                 \
+        (lpPerformanceCount.QuadPart >= 0)) {                       \
+        silk_Timer_cnt[ID]++;                                       \
+        silk_Timer_sum[ID] += lpPerformanceCount.QuadPart;          \
+        if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] )      \
+            silk_Timer_max[ID] = lpPerformanceCount.QuadPart;       \
+        if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] )      \
+            silk_Timer_min[ID] = lpPerformanceCount.QuadPart;       \
+    }                                                               \
+    silk_Timer_depth_ctr--;                                         \
+}
+#else
+#define TOC(TAG_NAME) {                                             \
+    unsigned long endTime;                                          \
+    static int init = 0;                                            \
+    static int ID = 0;                                              \
+    if( init == 0 )                                                 \
+    {                                                               \
+        int k;                                                      \
+        init = 1;                                                   \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {                 \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {      \
+                ID = k;                                             \
+                break;                                              \
+            }                                                       \
+        }                                                           \
+    }                                                               \
+    endTime = GetHighResolutionTime();                              \
+    endTime -= silk_Timer_start[ID];                                \
+    if((endTime < 100000000) &&                                     \
+        (endTime >= 0)) {                                           \
+        silk_Timer_cnt[ID]++;                                       \
+        silk_Timer_sum[ID] += endTime;                              \
+        if( endTime > silk_Timer_max[ID] )                          \
+            silk_Timer_max[ID] = endTime;                           \
+        if( endTime < silk_Timer_min[ID] )                          \
+            silk_Timer_min[ID] = endTime;                           \
+    }                                                               \
+        silk_Timer_depth_ctr--;                                     \
+}
+#endif
+
+#else /* SILK_TIC_TOC */
+
+/* define macros as empty strings */
+#define TIC(TAG_NAME)
+#define TOC(TAG_NAME)
+#define silk_TimerSave(FILE_NAME)
+
+#endif /* SILK_TIC_TOC */
+
+
+#if SILK_DEBUG
+/************************************/
+/* write data to file for debugging */
+/************************************/
+/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */
+
+#define silk_NUM_STORES_MAX                                  100
+extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
+extern int silk_debug_store_count;
+
+/* Faster way of storing the data */
+#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) {          \
+    static opus_int init = 0, cnt = 0;                              \
+    static FILE **fp;                                               \
+    if (init == 0) {                                                \
+        init = 1;                                                   \
+        cnt = silk_debug_store_count++;                             \
+        silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb");       \
+    }                                                               \
+    fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]);   \
+}
+
+/* Call this at the end of main() */
+#define SILK_DEBUG_STORE_CLOSE_FILES {                              \
+    opus_int i;                                                     \
+    for( i = 0; i < silk_debug_store_count; i++ ) {                 \
+        fclose( silk_debug_store_fp[ i ] );                         \
+    }                                                               \
+}
+
+#else /* SILK_DEBUG */
+
+/* define macros as empty strings */
+#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
+#define SILK_DEBUG_STORE_CLOSE_FILES
+
+#endif /* SILK_DEBUG */
+
+#endif /* SILK_DEBUG_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/dec_API.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/dec_API.c
new file mode 100644 (file)
index 0000000..973c497
--- /dev/null
@@ -0,0 +1,509 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "API.h"
+#include "main.h"
+#include "stack_alloc.h"
+#include "os_support.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#include "osce_structs.h"
+#ifdef ENABLE_OSCE_BWE
+#include "osce_features.h"
+#endif
+#endif
+
+/************************/
+/* Decoder Super Struct */
+/************************/
+typedef struct {
+    silk_decoder_state          channel_state[ DECODER_NUM_CHANNELS ];
+    stereo_dec_state                sStereo;
+    opus_int                         nChannelsAPI;
+    opus_int                         nChannelsInternal;
+    opus_int                         prev_decode_only_middle;
+#ifdef ENABLE_OSCE
+    OSCEModel                        osce_model;
+#endif
+} silk_decoder;
+
+/*********************/
+/* Decoder functions */
+/*********************/
+
+
+
+opus_int silk_LoadOSCEModels(void *decState, const unsigned char *data, int len)
+{
+#ifdef ENABLE_OSCE
+    opus_int ret = SILK_NO_ERROR;
+
+    ret = osce_load_models(&((silk_decoder *)decState)->osce_model, data, len);
+    ((silk_decoder *)decState)->osce_model.loaded = (ret == 0);
+    return ret;
+#else
+    (void) decState;
+    (void) data;
+    (void) len;
+    return SILK_NO_ERROR;
+#endif
+}
+
+opus_int silk_Get_Decoder_Size(                         /* O    Returns error code                              */
+    opus_int                        *decSizeBytes       /* O    Number of bytes in SILK decoder state           */
+)
+{
+    opus_int ret = SILK_NO_ERROR;
+
+    *decSizeBytes = sizeof( silk_decoder );
+
+    return ret;
+}
+
+/* Reset decoder state */
+opus_int silk_ResetDecoder(                              /* O    Returns error code                              */
+    void                            *decState           /* I/O  State                                           */
+)
+{
+    opus_int n, ret = SILK_NO_ERROR;
+    silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
+
+    for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
+        ret  = silk_reset_decoder( &channel_state[ n ] );
+    }
+    silk_memset(&((silk_decoder *)decState)->sStereo, 0, sizeof(((silk_decoder *)decState)->sStereo));
+    /* Not strictly needed, but it's cleaner that way */
+    ((silk_decoder *)decState)->prev_decode_only_middle = 0;
+
+    return ret;
+}
+
+
+opus_int silk_InitDecoder(                              /* O    Returns error code                              */
+    void                            *decState           /* I/O  State                                           */
+)
+{
+    opus_int n, ret = SILK_NO_ERROR;
+    silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
+#ifdef ENABLE_OSCE
+    ((silk_decoder *)decState)->osce_model.loaded = 0;
+#endif
+#ifndef USE_WEIGHTS_FILE
+    /* load osce models */
+    silk_LoadOSCEModels(decState, NULL, 0);
+#endif
+
+    for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
+        ret  = silk_init_decoder( &channel_state[ n ] );
+    }
+    silk_memset(&((silk_decoder *)decState)->sStereo, 0, sizeof(((silk_decoder *)decState)->sStereo));
+    /* Not strictly needed, but it's cleaner that way */
+    ((silk_decoder *)decState)->prev_decode_only_middle = 0;
+
+    return ret;
+}
+
+/* Decode a frame */
+opus_int silk_Decode(                                   /* O    Returns error code                              */
+    void*                           decState,           /* I/O  State                                           */
+    silk_DecControlStruct*          decControl,         /* I/O  Control Structure                               */
+    opus_int                        lostFlag,           /* I    0: no loss, 1 loss, 2 decode fec                */
+    opus_int                        newPacketFlag,      /* I    Indicates first decoder call for this packet    */
+    ec_dec                          *psRangeDec,        /* I/O  Compressor data structure                       */
+    opus_res                        *samplesOut,        /* O    Decoded output speech vector                    */
+    opus_int32                      *nSamplesOut,       /* O    Number of samples decoded                       */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState                  *lpcnet,
+#endif
+    int                             arch                /* I    Run-time architecture                           */
+)
+{
+    opus_int   i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
+    opus_int32 nSamplesOutDec, LBRR_symbol;
+    opus_int16 *samplesOut1_tmp[ 2 ];
+    VARDECL( opus_int16, samplesOut1_tmp_storage1 );
+    VARDECL( opus_int16, samplesOut2_tmp );
+    opus_int32 MS_pred_Q13[ 2 ] = { 0 };
+    opus_int16 *resample_out_ptr;
+    silk_decoder *psDec = ( silk_decoder * )decState;
+    silk_decoder_state *channel_state = psDec->channel_state;
+    opus_int has_side;
+    opus_int stereo_to_mono;
+#ifdef ENABLE_OSCE_BWE
+    VARDECL( opus_int16, resamp_buffer );
+#endif
+    SAVE_STACK;
+
+    celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
+
+    /**********************************/
+    /* Test if first frame in payload */
+    /**********************************/
+    if( newPacketFlag ) {
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            channel_state[ n ].nFramesDecoded = 0;  /* Used to count frames in packet */
+        }
+    }
+
+    /* If Mono -> Stereo transition in bitstream: init state of second channel */
+    if( decControl->nChannelsInternal > psDec->nChannelsInternal ) {
+        ret += silk_init_decoder( &channel_state[ 1 ] );
+    }
+
+    stereo_to_mono = decControl->nChannelsInternal == 1 && psDec->nChannelsInternal == 2 &&
+                     ( decControl->internalSampleRate == 1000*channel_state[ 0 ].fs_kHz );
+
+    if( channel_state[ 0 ].nFramesDecoded == 0 ) {
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            opus_int fs_kHz_dec;
+            if( decControl->payloadSize_ms == 0 ) {
+                /* Assuming packet loss, use 10 ms */
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 2;
+            } else if( decControl->payloadSize_ms == 10 ) {
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 2;
+            } else if( decControl->payloadSize_ms == 20 ) {
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 4;
+            } else if( decControl->payloadSize_ms == 40 ) {
+                channel_state[ n ].nFramesPerPacket = 2;
+                channel_state[ n ].nb_subfr = 4;
+            } else if( decControl->payloadSize_ms == 60 ) {
+                channel_state[ n ].nFramesPerPacket = 3;
+                channel_state[ n ].nb_subfr = 4;
+            } else {
+                celt_assert( 0 );
+                RESTORE_STACK;
+                return SILK_DEC_INVALID_FRAME_SIZE;
+            }
+            fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
+            if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
+                celt_assert( 0 );
+                RESTORE_STACK;
+                return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+            }
+            ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate );
+        }
+    }
+
+    if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) {
+        silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) );
+        silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) );
+        silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
+    }
+    psDec->nChannelsAPI      = decControl->nChannelsAPI;
+    psDec->nChannelsInternal = decControl->nChannelsInternal;
+
+    if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) {
+        ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+        RESTORE_STACK;
+        return( ret );
+    }
+
+    if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) {
+        /* First decoder call for this payload */
+        /* Decode VAD flags and LBRR flag */
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+                channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1);
+            }
+            channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1);
+        }
+        /* Decode LBRR flags */
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) );
+            if( channel_state[ n ].LBRR_flag ) {
+                if( channel_state[ n ].nFramesPerPacket == 1 ) {
+                    channel_state[ n ].LBRR_flags[ 0 ] = 1;
+                } else {
+                    LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1;
+                    for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+                        channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1;
+                    }
+                }
+            }
+        }
+
+        if( lostFlag == FLAG_DECODE_NORMAL ) {
+            /* Regular decoding: skip all LBRR data */
+            for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) {
+                for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+                    if( channel_state[ n ].LBRR_flags[ i ] ) {
+                        opus_int16 pulses[ MAX_FRAME_LENGTH ];
+                        opus_int condCoding;
+
+                        if( decControl->nChannelsInternal == 2 && n == 0 ) {
+                            silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+                            if( channel_state[ 1 ].LBRR_flags[ i ] == 0 ) {
+                                silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+                            }
+                        }
+                        /* Use conditional coding if previous frame available */
+                        if( i > 0 && channel_state[ n ].LBRR_flags[ i - 1 ] ) {
+                            condCoding = CODE_CONDITIONALLY;
+                        } else {
+                            condCoding = CODE_INDEPENDENTLY;
+                        }
+                        silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1, condCoding );
+                        silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType,
+                            channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length );
+                    }
+                }
+            }
+        }
+    }
+
+    /* Get MS predictor index */
+    if( decControl->nChannelsInternal == 2 ) {
+        if(   lostFlag == FLAG_DECODE_NORMAL ||
+            ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) )
+        {
+            silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+            /* For LBRR data, decode mid-only flag only if side-channel's LBRR flag is false */
+            if( ( lostFlag == FLAG_DECODE_NORMAL && channel_state[ 1 ].VAD_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) ||
+                ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 1 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) )
+            {
+                silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+            } else {
+                decode_only_middle = 0;
+            }
+        } else {
+            for( n = 0; n < 2; n++ ) {
+                MS_pred_Q13[ n ] = psDec->sStereo.pred_prev_Q13[ n ];
+            }
+        }
+    }
+
+    /* Reset side channel decoder prediction memory for first frame with side coding */
+    if( decControl->nChannelsInternal == 2 && decode_only_middle == 0 && psDec->prev_decode_only_middle == 1 ) {
+        silk_memset( psDec->channel_state[ 1 ].outBuf, 0, sizeof(psDec->channel_state[ 1 ].outBuf) );
+        silk_memset( psDec->channel_state[ 1 ].sLPC_Q14_buf, 0, sizeof(psDec->channel_state[ 1 ].sLPC_Q14_buf) );
+        psDec->channel_state[ 1 ].lagPrev        = 100;
+        psDec->channel_state[ 1 ].LastGainIndex  = 10;
+        psDec->channel_state[ 1 ].prevSignalType = TYPE_NO_VOICE_ACTIVITY;
+        psDec->channel_state[ 1 ].first_frame_after_reset = 1;
+    }
+
+    /* Check if the temp buffer fits into the output PCM buffer. If it fits,
+       we can delay allocating the temp buffer until after the SILK peak stack
+       usage. We need to use a < and not a <= because of the two extra samples. */
+    ALLOC( samplesOut1_tmp_storage1, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ),
+           opus_int16 );
+    samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage1;
+    samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage1 + channel_state[ 0 ].frame_length + 2;
+
+    if( lostFlag == FLAG_DECODE_NORMAL ) {
+        has_side = !decode_only_middle;
+    } else {
+        has_side = !psDec->prev_decode_only_middle
+              || (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 );
+    }
+    channel_state[ 0 ].sPLC.enable_deep_plc = decControl->enable_deep_plc;
+    /* Call decoder for one frame */
+    for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+        if( n == 0 || has_side ) {
+            opus_int FrameIndex;
+            opus_int condCoding;
+
+            FrameIndex = channel_state[ 0 ].nFramesDecoded - n;
+            /* Use independent coding if no previous frame available */
+            if( FrameIndex <= 0 ) {
+                condCoding = CODE_INDEPENDENTLY;
+            } else if( lostFlag == FLAG_DECODE_LBRR ) {
+                condCoding = channel_state[ n ].LBRR_flags[ FrameIndex - 1 ] ? CODE_CONDITIONALLY : CODE_INDEPENDENTLY;
+            } else if( n > 0 && psDec->prev_decode_only_middle ) {
+                /* If we skipped a side frame in this packet, we don't
+                   need LTP scaling; the LTP state is well-defined. */
+                condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING;
+            } else {
+                condCoding = CODE_CONDITIONALLY;
+            }
+#ifdef ENABLE_OSCE
+            if ( channel_state[n].osce.method != decControl->osce_method ) {
+                osce_reset( &channel_state[n].osce, decControl->osce_method );
+            }
+#endif
+            ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding,
+#ifdef ENABLE_DEEP_PLC
+                n == 0 ? lpcnet : NULL,
+#endif
+#ifdef ENABLE_OSCE
+                &psDec->osce_model,
+#endif
+                arch);
+        } else {
+            silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
+        }
+        channel_state[ n ].nFramesDecoded++;
+    }
+
+    if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
+        /* Convert Mid/Side to Left/Right */
+        silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec );
+    } else {
+        /* Buffering */
+        silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
+        silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
+    }
+
+    /* Number of output samples */
+    *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
+
+    /* Set up pointers to temp buffers */
+    ALLOC( samplesOut2_tmp, *nSamplesOut, opus_int16 );
+    resample_out_ptr = samplesOut2_tmp;
+
+#ifdef ENABLE_OSCE_BWE
+    ALLOC(resamp_buffer, 3 * MAX_FRAME_LENGTH, opus_int16);
+#endif
+
+    for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
+
+#ifdef ENABLE_OSCE_BWE
+        /* Resample or extend decoded signal to API_sampleRate */
+        if (decControl->osce_extended_mode == OSCE_MODE_SILK_BBWE) {
+            silk_assert(decControl->API_sampleRate == 48000);
+
+            if (decControl->prev_osce_extended_mode != OSCE_MODE_SILK_BBWE) {
+                /* Reset the BWE state */
+                osce_bwe_reset( &channel_state[ n ].osce_bwe );
+            }
+
+            osce_bwe(&psDec->osce_model, &channel_state[ n ].osce_bwe,
+                resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec, arch);
+
+            if (decControl->prev_osce_extended_mode == OSCE_MODE_SILK_ONLY ||
+                decControl->prev_osce_extended_mode == OSCE_MODE_HYBRID) {
+                    /* cross-fade with upsampled signal */
+                    silk_resampler( &channel_state[ n ].resampler_state, resamp_buffer, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+                    osce_bwe_cross_fade_10ms(resample_out_ptr, resamp_buffer, 480);
+            }
+        } else {
+            ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+            if (decControl->prev_osce_extended_mode == OSCE_MODE_SILK_BBWE && decControl->internalSampleRate == 16000) {
+                /* fade out if internal sample rate did not change */
+                osce_bwe(&psDec->osce_model, &channel_state[ n ].osce_bwe,
+                    resamp_buffer, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec, arch);
+                /* cross-fade with upsampled signal */
+                osce_bwe_cross_fade_10ms(resample_out_ptr, resamp_buffer, 480);
+            }
+        }
+#else
+        /* Resample decoded signal to API_sampleRate */
+        ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+#endif
+        /* Interleave if stereo output and stereo stream */
+        if( decControl->nChannelsAPI == 2 ) {
+            for( i = 0; i < *nSamplesOut; i++ ) {
+                samplesOut[ n + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
+            }
+        } else {
+            for( i = 0; i < *nSamplesOut; i++ ) {
+                samplesOut[ i ] = INT16TORES(resample_out_ptr[ i ]);
+            }
+        }
+    }
+
+#ifdef ENABLE_OSCE_BWE
+    decControl->prev_osce_extended_mode = decControl->osce_extended_mode;
+#endif
+
+    /* Create two channel output from mono stream */
+    if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) {
+        if ( stereo_to_mono ){
+            /* Resample right channel for newly collapsed stereo just in case
+               we weren't doing collapsing when switching to mono */
+            ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec );
+
+            for( i = 0; i < *nSamplesOut; i++ ) {
+                samplesOut[ 1 + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
+            }
+        } else {
+            for( i = 0; i < *nSamplesOut; i++ ) {
+                samplesOut[ 1 + 2 * i ] = samplesOut[ 0 + 2 * i ];
+            }
+        }
+    }
+
+    /* Export pitch lag, measured at 48 kHz sampling rate */
+    if( channel_state[ 0 ].prevSignalType == TYPE_VOICED ) {
+        int mult_tab[ 3 ] = { 6, 4, 3 };
+        decControl->prevPitchLag = channel_state[ 0 ].lagPrev * mult_tab[ ( channel_state[ 0 ].fs_kHz - 8 ) >> 2 ];
+    } else {
+        decControl->prevPitchLag = 0;
+    }
+
+    if( lostFlag == FLAG_PACKET_LOST ) {
+       /* On packet loss, remove the gain clamping to prevent having the energy "bounce back"
+          if we lose packets when the energy is going down */
+       for ( i = 0; i < psDec->nChannelsInternal; i++ )
+          psDec->channel_state[ i ].LastGainIndex = 10;
+    } else {
+       psDec->prev_decode_only_middle = decode_only_middle;
+    }
+    RESTORE_STACK;
+    return ret;
+}
+
+#if 0
+/* Getting table of contents for a packet */
+opus_int silk_get_TOC(
+    const opus_uint8                *payload,           /* I    Payload data                                */
+    const opus_int                  nBytesIn,           /* I    Number of input bytes                       */
+    const opus_int                  nFramesPerPayload,  /* I    Number of SILK frames per payload           */
+    silk_TOC_struct                 *Silk_TOC           /* O    Type of content                             */
+)
+{
+    opus_int i, flags, ret = SILK_NO_ERROR;
+
+    if( nBytesIn < 1 ) {
+        return -1;
+    }
+    if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) {
+        return -1;
+    }
+
+    silk_memset( Silk_TOC, 0, sizeof( *Silk_TOC ) );
+
+    /* For stereo, extract the flags for the mid channel */
+    flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 );
+
+    Silk_TOC->inbandFECFlag = flags & 1;
+    for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) {
+        flags = silk_RSHIFT( flags, 1 );
+        Silk_TOC->VADFlags[ i ] = flags & 1;
+        Silk_TOC->VADFlag |= flags & 1;
+    }
+
+    return ret;
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_core.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_core.c
new file mode 100644 (file)
index 0000000..9fe91cc
--- /dev/null
@@ -0,0 +1,243 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+
+/**********************************************************/
+/* Core decoder. Performs inverse NSQ operation LTP + LPC */
+/**********************************************************/
+void silk_decode_core(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
+    silk_decoder_control        *psDecCtrl,                     /* I    Decoder control                             */
+    opus_int16                  xq[],                           /* O    Decoded speech                              */
+    const opus_int16            pulses[ MAX_FRAME_LENGTH ],     /* I    Pulse signal                                */
+    int                         arch                            /* I    Run-time architecture                       */
+)
+{
+    opus_int   i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
+    opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
+    VARDECL( opus_int16, sLTP );
+    VARDECL( opus_int32, sLTP_Q15 );
+    opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
+    opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14;
+    VARDECL( opus_int32, res_Q14 );
+    VARDECL( opus_int32, sLPC_Q14 );
+    SAVE_STACK;
+
+    silk_assert( psDec->prev_gain_Q16 != 0 );
+
+    ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
+    ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
+    ALLOC( res_Q14, psDec->subfr_length, opus_int32 );
+    /* Work around a clang bug (verified with clang 6.0 through clang 20.1.0) that causes the last
+       memset to be flagged as an invalid read by valgrind (not caught by asan). */
+#if defined(__clang__) && defined(VAR_ARRAYS)
+    ALLOC( sLPC_Q14, MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER, opus_int32 );
+#else
+    ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 );
+#endif
+
+    offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
+
+    if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
+        NLSF_interpolation_flag = 1;
+    } else {
+        NLSF_interpolation_flag = 0;
+    }
+
+    /* Decode excitation */
+    rand_seed = psDec->indices.Seed;
+    for( i = 0; i < psDec->frame_length; i++ ) {
+        rand_seed = silk_RAND( rand_seed );
+        psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 );
+        if( psDec->exc_Q14[ i ] > 0 ) {
+            psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4;
+        } else
+        if( psDec->exc_Q14[ i ] < 0 ) {
+            psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
+        }
+        psDec->exc_Q14[ i ] += offset_Q10 << 4;
+        if( rand_seed < 0 ) {
+           psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
+        }
+
+        rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
+    }
+
+    /* Copy LPC state */
+    silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+    pexc_Q14 = psDec->exc_Q14;
+    pxq      = xq;
+    sLTP_buf_idx = psDec->ltp_mem_length;
+    /* Loop over subframes */
+    for( k = 0; k < psDec->nb_subfr; k++ ) {
+        pres_Q14 = res_Q14;
+        A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
+
+        /* Preload LPC coefficients to array on stack. Gives small performance gain */
+        silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+        B_Q14        = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
+        signalType   = psDec->indices.signalType;
+
+        Gain_Q10     = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
+        inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 );
+
+        /* Calculate gain adjustment factor */
+        if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) {
+            gain_adj_Q16 =  silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 );
+
+            /* Scale short term state */
+            for( i = 0; i < MAX_LPC_ORDER; i++ ) {
+                sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] );
+            }
+        } else {
+            gain_adj_Q16 = (opus_int32)1 << 16;
+        }
+
+        /* Save inv_gain */
+        silk_assert( inv_gain_Q31 != 0 );
+        psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ];
+
+        /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
+        if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
+            psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
+
+            silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+            B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
+
+            signalType = TYPE_VOICED;
+            psDecCtrl->pitchL[ k ] = psDec->lagPrev;
+        }
+
+        if( signalType == TYPE_VOICED ) {
+            /* Voiced */
+            lag = psDecCtrl->pitchL[ k ];
+
+            /* Re-whitening */
+            if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
+                /* Rewhiten with new A coefs */
+                start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
+                celt_assert( start_idx > 0 );
+
+                if( k == 2 ) {
+                    silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
+                }
+
+                silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
+                    A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order, arch );
+
+                /* After rewhitening the LTP state is unscaled */
+                if( k == 0 ) {
+                    /* Do LTP downscaling to reduce inter-packet dependency */
+                    inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
+                }
+                for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
+                    sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
+                }
+            } else {
+                /* Update LTP state when Gain changes */
+                if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+                    for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
+                        sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
+                    }
+                }
+            }
+        }
+
+        /* Long-term prediction */
+        if( signalType == TYPE_VOICED ) {
+            /* Set up pointer */
+            pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+            for( i = 0; i < psDec->subfr_length; i++ ) {
+                /* Unrolled loop */
+                /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+                LTP_pred_Q13 = 2;
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
+                pred_lag_ptr++;
+
+                /* Generate LPC excitation */
+                pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 );
+
+                /* Update states */
+                sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 );
+                sLTP_buf_idx++;
+            }
+        } else {
+            pres_Q14 = pexc_Q14;
+        }
+
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            /* Short-term prediction */
+            celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+            LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
+            if( psDec->LPC_order == 16 ) {
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
+            }
+
+            /* Add prediction to LPC excitation */
+            sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( pres_Q14[ i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
+            /* Scale with gain */
+            pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
+        }
+
+        /* Update LPC filter state */
+        silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+        pexc_Q14 += psDec->subfr_length;
+        pxq      += psDec->subfr_length;
+    }
+
+    /* Save LPC state */
+    silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_frame.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_frame.c
new file mode 100644 (file)
index 0000000..9bc4ca2
--- /dev/null
@@ -0,0 +1,169 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+#include "PLC.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+/****************/
+/* Decode frame */
+/****************/
+opus_int silk_decode_frame(
+    silk_decoder_state          *psDec,                         /* I/O  Pointer to Silk decoder state               */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int16                  pOut[],                         /* O    Pointer to output speech frame              */
+    opus_int32                  *pN,                            /* O    Pointer to size of output frame             */
+    opus_int                    lostFlag,                       /* I    0: no loss, 1 loss, 2 decode fec            */
+    opus_int                    condCoding,                     /* I    The type of conditional coding to use       */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState              *lpcnet,
+#endif
+#ifdef ENABLE_OSCE
+    OSCEModel                   *osce_model,
+#endif
+    int                         arch                            /* I    Run-time architecture                       */
+)
+{
+    VARDECL( silk_decoder_control, psDecCtrl );
+    opus_int         L, mv_len, ret = 0;
+    SAVE_STACK;
+
+    L = psDec->frame_length;
+    ALLOC( psDecCtrl, 1, silk_decoder_control );
+    psDecCtrl->LTP_scale_Q14 = 0;
+
+    /* Safety checks */
+    celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+
+    if(   lostFlag == FLAG_DECODE_NORMAL ||
+        ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
+    {
+        VARDECL( opus_int16, pulses );
+#ifdef ENABLE_OSCE
+        opus_int32  ec_start;
+        ec_start = ec_tell(psRangeDec);
+#endif
+        ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
+                       ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int16 );
+        /*********************************************/
+        /* Decode quantization indices of side info  */
+        /*********************************************/
+        silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding );
+
+        /*********************************************/
+        /* Decode quantization indices of excitation */
+        /*********************************************/
+        silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType,
+                psDec->indices.quantOffsetType, psDec->frame_length );
+
+        /********************************************/
+        /* Decode parameters and pulse signal       */
+        /********************************************/
+        silk_decode_parameters( psDec, psDecCtrl, condCoding );
+
+        /********************************************************/
+        /* Run inverse NSQ                                      */
+        /********************************************************/
+        silk_decode_core( psDec, psDecCtrl, pOut, pulses, arch );
+
+        /*************************/
+        /* Update output buffer. */
+        /*************************/
+        celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
+        mv_len = psDec->ltp_mem_length - psDec->frame_length;
+        silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
+        silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
+
+#ifdef ENABLE_OSCE
+        /********************************************************/
+        /* Run SILK enhancer                                    */
+        /********************************************************/
+        osce_enhance_frame( osce_model, psDec, psDecCtrl, pOut, ec_tell(psRangeDec) - ec_start, arch );
+#endif
+
+        /********************************************************/
+        /* Update PLC state                                     */
+        /********************************************************/
+        silk_PLC( psDec, psDecCtrl, pOut, 0,
+#ifdef ENABLE_DEEP_PLC
+            lpcnet,
+#endif
+            arch );
+
+        psDec->lossCnt = 0;
+        psDec->prevSignalType = psDec->indices.signalType;
+        celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+
+        /* A frame has been decoded without errors */
+        psDec->first_frame_after_reset = 0;
+    } else {
+        /* Handle packet loss by extrapolation */
+        silk_PLC( psDec, psDecCtrl, pOut, 1,
+#ifdef ENABLE_DEEP_PLC
+            lpcnet,
+#endif
+            arch );
+
+#ifdef ENABLE_OSCE
+        osce_reset( &psDec->osce, psDec->osce.method );
+#endif
+        /*************************/
+        /* Update output buffer. */
+        /*************************/
+        celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
+        mv_len = psDec->ltp_mem_length - psDec->frame_length;
+        silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
+        silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
+    }
+
+    /************************************************/
+    /* Comfort noise generation / estimation        */
+    /************************************************/
+    silk_CNG( psDec, psDecCtrl, pOut, L );
+
+    /****************************************************************/
+    /* Ensure smooth connection of extrapolated and good frames     */
+    /****************************************************************/
+    silk_PLC_glue_frames( psDec, pOut, L );
+
+    /* Update some decoder state variables */
+    psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];
+
+    /* Set output frame length */
+    *pN = L;
+
+    RESTORE_STACK;
+    return ret;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_indices.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_indices.c
new file mode 100644 (file)
index 0000000..268e427
--- /dev/null
@@ -0,0 +1,151 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode side-information parameters from payload */
+void silk_decode_indices(
+    silk_decoder_state          *psDec,                         /* I/O  State                                       */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int                    FrameIndex,                     /* I    Frame number                                */
+    opus_int                    decode_LBRR,                    /* I    Flag indicating LBRR data is being decoded  */
+    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
+)
+{
+    opus_int   i, k, Ix;
+    opus_int   decode_absolute_lagIndex, delta_lagIndex;
+    opus_int16 ec_ix[ MAX_LPC_ORDER ];
+    opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
+
+    /*******************************************/
+    /* Decode signal type and quantizer offset */
+    /*******************************************/
+    if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) {
+        Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2;
+    } else {
+        Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 );
+    }
+    psDec->indices.signalType      = (opus_int8)silk_RSHIFT( Ix, 1 );
+    psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 );
+
+    /****************/
+    /* Decode gains */
+    /****************/
+    /* First subframe */
+    if( condCoding == CODE_CONDITIONALLY ) {
+        /* Conditional coding */
+        psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+    } else {
+        /* Independent coding, in two stages: MSB bits followed by 3 LSBs */
+        psDec->indices.GainsIndices[ 0 ]  = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 );
+        psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 );
+    }
+
+    /* Remaining subframes */
+    for( i = 1; i < psDec->nb_subfr; i++ ) {
+        psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+    }
+
+    /**********************/
+    /* Decode LSF Indices */
+    /**********************/
+    psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
+    silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
+    celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+    for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
+        Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
+        if( Ix == 0 ) {
+            Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+        } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) {
+            Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+        }
+        psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE );
+    }
+
+    /* Decode LSF interpolation factor */
+    if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+        psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 );
+    } else {
+        psDec->indices.NLSFInterpCoef_Q2 = 4;
+    }
+
+    if( psDec->indices.signalType == TYPE_VOICED )
+    {
+        /*********************/
+        /* Decode pitch lags */
+        /*********************/
+        /* Get lag index */
+        decode_absolute_lagIndex = 1;
+        if( condCoding == CODE_CONDITIONALLY && psDec->ec_prevSignalType == TYPE_VOICED ) {
+            /* Decode Delta index */
+            delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 );
+            if( delta_lagIndex > 0 ) {
+                delta_lagIndex = delta_lagIndex - 9;
+                psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex );
+                decode_absolute_lagIndex = 0;
+            }
+        }
+        if( decode_absolute_lagIndex ) {
+            /* Absolute decoding */
+            psDec->indices.lagIndex  = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * silk_RSHIFT( psDec->fs_kHz, 1 );
+            psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 );
+        }
+        psDec->ec_prevLagIndex = psDec->indices.lagIndex;
+
+        /* Get contour index */
+        psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 );
+
+        /********************/
+        /* Decode LTP gains */
+        /********************/
+        /* Decode PERIndex value */
+        psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 );
+
+        for( k = 0; k < psDec->nb_subfr; k++ ) {
+            psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 );
+        }
+
+        /**********************/
+        /* Decode LTP scaling */
+        /**********************/
+        if( condCoding == CODE_INDEPENDENTLY ) {
+            psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 );
+        } else {
+            psDec->indices.LTP_scaleIndex = 0;
+        }
+    }
+    psDec->ec_prevSignalType = psDec->indices.signalType;
+
+    /***************/
+    /* Decode seed */
+    /***************/
+    psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_parameters.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_parameters.c
new file mode 100644 (file)
index 0000000..a56a409
--- /dev/null
@@ -0,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode parameters from payload */
+void silk_decode_parameters(
+    silk_decoder_state          *psDec,                         /* I/O  State                                       */
+    silk_decoder_control        *psDecCtrl,                     /* I/O  Decoder control                             */
+    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
+)
+{
+    opus_int   i, k, Ix;
+    opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ];
+    const opus_int8 *cbk_ptr_Q7;
+
+    /* Dequant Gains */
+    silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices,
+        &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr );
+
+    /****************/
+    /* Decode NLSFs */
+    /****************/
+    silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
+
+    /* Convert NLSF parameters to AR prediction filter coefficients */
+    silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
+
+    /* If just reset, e.g., because internal Fs changed, do not allow interpolation */
+    /* improves the case of packet loss in the first frame after a switch           */
+    if( psDec->first_frame_after_reset == 1 ) {
+        psDec->indices.NLSFInterpCoef_Q2 = 4;
+    }
+
+    if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) {
+        /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
+        /* the previous NLSF1, and the current NLSF1                                   */
+        for( i = 0; i < psDec->LPC_order; i++ ) {
+            pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + silk_RSHIFT( silk_MUL( psDec->indices.NLSFInterpCoef_Q2,
+                pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 );
+        }
+
+        /* Convert NLSF parameters to AR prediction filter coefficients */
+        silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
+    } else {
+        /* Copy LPC coefficients for first half from second half */
+        silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
+    }
+
+    silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );
+
+    /* After a packet loss do BWE of LPC coefs */
+    if( psDec->lossCnt ) {
+        silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+        silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+    }
+
+    if( psDec->indices.signalType == TYPE_VOICED ) {
+        /*********************/
+        /* Decode pitch lags */
+        /*********************/
+
+        /* Decode pitch values */
+        silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr );
+
+        /* Decode Codebook Index */
+        cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */
+
+        for( k = 0; k < psDec->nb_subfr; k++ ) {
+            Ix = psDec->indices.LTPIndex[ k ];
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = silk_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 );
+            }
+        }
+
+        /**********************/
+        /* Decode LTP scaling */
+        /**********************/
+        Ix = psDec->indices.LTP_scaleIndex;
+        psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ];
+    } else {
+        silk_memset( psDecCtrl->pitchL,      0,             psDec->nb_subfr * sizeof( opus_int   ) );
+        silk_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) );
+        psDec->indices.PERIndex  = 0;
+        psDecCtrl->LTP_scale_Q14 = 0;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pitch.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pitch.c
new file mode 100644 (file)
index 0000000..fd1b6bf
--- /dev/null
@@ -0,0 +1,77 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/***********************************************************
+* Pitch analyser function
+********************************************************** */
+#include "SigProc_FIX.h"
+#include "pitch_est_defines.h"
+
+void silk_decode_pitch(
+    opus_int16                  lagIndex,           /* I                                                                */
+    opus_int8                   contourIndex,       /* O                                                                */
+    opus_int                    pitch_lags[],       /* O    4 pitch values                                              */
+    const opus_int              Fs_kHz,             /* I    sampling frequency (kHz)                                    */
+    const opus_int              nb_subfr            /* I    number of sub frames                                        */
+)
+{
+    opus_int   lag, k, min_lag, max_lag, cbk_size;
+    const opus_int8 *Lag_CB_ptr;
+
+    if( Fs_kHz == 8 ) {
+        if( nb_subfr == PE_MAX_NB_SUBFR ) {
+            Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE2_EXT;
+        } else {
+            celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+            Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE2_10MS;
+        }
+    } else {
+        if( nb_subfr == PE_MAX_NB_SUBFR ) {
+            Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE3_MAX;
+        } else {
+            celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+            Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE3_10MS;
+        }
+    }
+
+    min_lag = silk_SMULBB( PE_MIN_LAG_MS, Fs_kHz );
+    max_lag = silk_SMULBB( PE_MAX_LAG_MS, Fs_kHz );
+    lag = min_lag + lagIndex;
+
+    for( k = 0; k < nb_subfr; k++ ) {
+        pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size );
+        pitch_lags[ k ] = silk_LIMIT( pitch_lags[ k ], min_lag, max_lag );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pulses.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decode_pulses.c
new file mode 100644 (file)
index 0000000..a56d2d3
--- /dev/null
@@ -0,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*********************************************/
+/* Decode quantization indices of excitation */
+/*********************************************/
+void silk_decode_pulses(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int16                  pulses[],                       /* O    Excitation signal                           */
+    const opus_int              signalType,                     /* I    Sigtype                                     */
+    const opus_int              quantOffsetType,                /* I    quantOffsetType                             */
+    const opus_int              frame_length                    /* I    Frame length                                */
+)
+{
+    opus_int   i, j, k, iter, abs_q, nLS, RateLevelIndex;
+    opus_int   sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
+    opus_int16 *pulses_ptr;
+    const opus_uint8 *cdf_ptr;
+
+    /*********************/
+    /* Decode rate level */
+    /*********************/
+    RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
+
+    /* Calculate number of shell blocks */
+    silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
+    iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
+        celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+        iter++;
+    }
+
+    /***************************************************/
+    /* Sum-Weighted-Pulses Decoding                    */
+    /***************************************************/
+    cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
+    for( i = 0; i < iter; i++ ) {
+        nLshifts[ i ] = 0;
+        sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
+
+        /* LSB indication */
+        while( sum_pulses[ i ] == SILK_MAX_PULSES + 1 ) {
+            nLshifts[ i ]++;
+            /* When we've already got 10 LSBs, we shift the table to not allow (SILK_MAX_PULSES + 1) */
+            sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
+                    silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + ( nLshifts[ i ] == 10 ), 8 );
+        }
+    }
+
+    /***************************************************/
+    /* Shell decoding                                  */
+    /***************************************************/
+    for( i = 0; i < iter; i++ ) {
+        if( sum_pulses[ i ] > 0 ) {
+            silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
+        } else {
+            silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( pulses[0] ) );
+        }
+    }
+
+    /***************************************************/
+    /* LSB Decoding                                    */
+    /***************************************************/
+    for( i = 0; i < iter; i++ ) {
+        if( nLshifts[ i ] > 0 ) {
+            nLS = nLshifts[ i ];
+            pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
+            for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
+                abs_q = pulses_ptr[ k ];
+                for( j = 0; j < nLS; j++ ) {
+                    abs_q = silk_LSHIFT( abs_q, 1 );
+                    abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 );
+                }
+                pulses_ptr[ k ] = abs_q;
+            }
+            /* Mark the number of pulses non-zero for sign decoding. */
+            sum_pulses[ i ] |= nLS << 5;
+        }
+    }
+
+    /****************************************/
+    /* Decode and add signs to pulse signal */
+    /****************************************/
+    silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decoder_set_fs.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/decoder_set_fs.c
new file mode 100644 (file)
index 0000000..c6136c7
--- /dev/null
@@ -0,0 +1,107 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Set decoder sampling rate */
+opus_int silk_decoder_set_fs(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state pointer                       */
+    opus_int                    fs_kHz,                         /* I    Sampling frequency (kHz)                    */
+    opus_int32                  fs_API_Hz                       /* I    API Sampling frequency (Hz)                 */
+)
+{
+    opus_int frame_length, ret = 0;
+
+    celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+    celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+
+    /* New (sub)frame length */
+    psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
+    frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length );
+
+    /* Initialize resampler when switching internal or external sampling frequency */
+    if( psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz ) {
+        /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */
+        ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 );
+
+        psDec->fs_API_hz = fs_API_Hz;
+    }
+
+    if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) {
+        if( fs_kHz == 8 ) {
+            if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
+            } else {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
+            }
+        } else {
+            if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF;
+            } else {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
+            }
+        }
+        if( psDec->fs_kHz != fs_kHz ) {
+            psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
+            if( fs_kHz == 8 || fs_kHz == 12 ) {
+                psDec->LPC_order = MIN_LPC_ORDER;
+                psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB;
+            } else {
+                psDec->LPC_order = MAX_LPC_ORDER;
+                psDec->psNLSF_CB = &silk_NLSF_CB_WB;
+            }
+            if( fs_kHz == 16 ) {
+                psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
+            } else if( fs_kHz == 12 ) {
+                psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
+            } else if( fs_kHz == 8 ) {
+                psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
+            } else {
+                /* unsupported sampling rate */
+                celt_assert( 0 );
+            }
+            psDec->first_frame_after_reset = 1;
+            psDec->lagPrev                 = 100;
+            psDec->LastGainIndex           = 10;
+            psDec->prevSignalType          = TYPE_NO_VOICE_ACTIVITY;
+            silk_memset( psDec->outBuf, 0, sizeof(psDec->outBuf));
+            silk_memset( psDec->sLPC_Q14_buf, 0, sizeof(psDec->sLPC_Q14_buf) );
+        }
+
+        psDec->fs_kHz       = fs_kHz;
+        psDec->frame_length = frame_length;
+    }
+
+    /* Check that settings are valid */
+    celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+
+    return ret;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/define.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/define.h
new file mode 100644 (file)
index 0000000..caed671
--- /dev/null
@@ -0,0 +1,231 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_DEFINE_H
+#define SILK_DEFINE_H
+
+#include "errors.h"
+#include "typedef.h"
+
+
+/* Max number of encoder channels (1/2) */
+#define ENCODER_NUM_CHANNELS                    2
+/* Number of decoder channels (1/2) */
+#define DECODER_NUM_CHANNELS                    2
+
+#define MAX_FRAMES_PER_PACKET                   3
+
+/* Limits on bitrate */
+#define MIN_TARGET_RATE_BPS                     5000
+#define MAX_TARGET_RATE_BPS                     80000
+
+/* LBRR thresholds */
+#define LBRR_NB_MIN_RATE_BPS                    12000
+#define LBRR_MB_MIN_RATE_BPS                    14000
+#define LBRR_WB_MIN_RATE_BPS                    16000
+
+/* DTX settings */
+#define NB_SPEECH_FRAMES_BEFORE_DTX             10      /* eq 200 ms */
+#define MAX_CONSECUTIVE_DTX                     20      /* eq 400 ms */
+#define DTX_ACTIVITY_THRESHOLD                  0.1f
+
+/* VAD decision */
+#define VAD_NO_DECISION                         -1
+#define VAD_NO_ACTIVITY                         0
+#define VAD_ACTIVITY                            1
+
+/* Maximum sampling frequency */
+#define MAX_FS_KHZ                              16
+#ifdef ENABLE_QEXT
+#define MAX_API_FS_KHZ                          96
+#else
+#define MAX_API_FS_KHZ                          48
+#endif
+
+/* Signal types */
+#define TYPE_NO_VOICE_ACTIVITY                  0
+#define TYPE_UNVOICED                           1
+#define TYPE_VOICED                             2
+
+/* Conditional coding types */
+#define CODE_INDEPENDENTLY                      0
+#define CODE_INDEPENDENTLY_NO_LTP_SCALING       1
+#define CODE_CONDITIONALLY                      2
+
+/* Settings for stereo processing */
+#define STEREO_QUANT_TAB_SIZE                   16
+#define STEREO_QUANT_SUB_STEPS                  5
+#define STEREO_INTERP_LEN_MS                    8       /* must be even */
+#define STEREO_RATIO_SMOOTH_COEF                0.01    /* smoothing coef for signal norms and stereo width */
+
+/* Range of pitch lag estimates */
+#define PITCH_EST_MIN_LAG_MS                    2       /* 2 ms -> 500 Hz */
+#define PITCH_EST_MAX_LAG_MS                    18      /* 18 ms -> 56 Hz */
+
+/* Maximum number of subframes */
+#define MAX_NB_SUBFR                            4
+
+/* Number of samples per frame */
+#define LTP_MEM_LENGTH_MS                       20
+#define SUB_FRAME_LENGTH_MS                     5
+#define MAX_SUB_FRAME_LENGTH                    ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ )
+#define MAX_FRAME_LENGTH_MS                     ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR )
+#define MAX_FRAME_LENGTH                        ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for pitch analysis */
+#define LA_PITCH_MS                             2
+#define LA_PITCH_MAX                            ( LA_PITCH_MS * MAX_FS_KHZ )
+
+/* Order of LPC used in find pitch */
+#define MAX_FIND_PITCH_LPC_ORDER                16
+
+/* Length of LPC window used in find pitch */
+#define FIND_PITCH_LPC_WIN_MS                   ( 20 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MS_2_SF              ( 10 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MAX                  ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for noise shape analysis */
+#define LA_SHAPE_MS                             5
+#define LA_SHAPE_MAX                            ( LA_SHAPE_MS * MAX_FS_KHZ )
+
+/* Maximum length of LPC window used in noise shape analysis */
+#define SHAPE_LPC_WIN_MAX                       ( 15 * MAX_FS_KHZ )
+
+/* dB level of lowest gain quantization level */
+#define MIN_QGAIN_DB                            2
+/* dB level of highest gain quantization level */
+#define MAX_QGAIN_DB                            88
+/* Number of gain quantization levels */
+#define N_LEVELS_QGAIN                          64
+/* Max increase in gain quantization index */
+#define MAX_DELTA_GAIN_QUANT                    36
+/* Max decrease in gain quantization index */
+#define MIN_DELTA_GAIN_QUANT                    -4
+
+/* Quantization offsets (multiples of 4) */
+#define OFFSET_VL_Q10                           32
+#define OFFSET_VH_Q10                           100
+#define OFFSET_UVL_Q10                          100
+#define OFFSET_UVH_Q10                          240
+
+#define QUANT_LEVEL_ADJUST_Q10                  80
+
+/* Maximum numbers of iterations used to stabilize an LPC vector */
+#define MAX_LPC_STABILIZE_ITERATIONS            16
+#define MAX_PREDICTION_POWER_GAIN               1e4f
+#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET   1e2f
+
+#define MAX_LPC_ORDER                           16
+#define MIN_LPC_ORDER                           10
+
+/* Find Pred Coef defines */
+#define LTP_ORDER                               5
+
+/* LTP quantization settings */
+#define NB_LTP_CBKS                             3
+
+/* Flag to use harmonic noise shaping */
+#define USE_HARM_SHAPING                        1
+
+/* Max LPC order of noise shaping filters */
+#define MAX_SHAPE_LPC_ORDER                     24
+
+#define HARM_SHAPE_FIR_TAPS                     3
+
+/* Maximum number of delayed decision states */
+#define MAX_DEL_DEC_STATES                      4
+
+#define LTP_BUF_LENGTH                          512
+#define LTP_MASK                                ( LTP_BUF_LENGTH - 1 )
+
+#define DECISION_DELAY                          40
+
+/* Number of subframes for excitation entropy coding */
+#define SHELL_CODEC_FRAME_LENGTH                16
+#define LOG2_SHELL_CODEC_FRAME_LENGTH           4
+#define MAX_NB_SHELL_BLOCKS                     ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH )
+
+/* Number of rate levels, for entropy coding of excitation */
+#define N_RATE_LEVELS                           10
+
+/* Maximum sum of pulses per shell coding frame */
+#define SILK_MAX_PULSES                         16
+
+#define MAX_MATRIX_SIZE                         MAX_LPC_ORDER /* Max of LPC Order and LTP order */
+
+# define NSQ_LPC_BUF_LENGTH                     MAX_LPC_ORDER
+
+/***************************/
+/* Voice activity detector */
+/***************************/
+#define VAD_N_BANDS                             4
+
+#define VAD_INTERNAL_SUBFRAMES_LOG2             2
+#define VAD_INTERNAL_SUBFRAMES                  ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 )
+
+#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16         1024    /* Must be <  4096 */
+#define VAD_NOISE_LEVELS_BIAS                   50
+
+/* Sigmoid settings */
+#define VAD_NEGATIVE_OFFSET_Q5                  128     /* sigmoid is 0 at -128 */
+#define VAD_SNR_FACTOR_Q16                      45000
+
+/* smoothing for SNR measurement */
+#define VAD_SNR_SMOOTH_COEF_Q18                 4096
+
+/* Size of the piecewise linear cosine approximation table for the LSFs */
+#define LSF_COS_TAB_SZ_FIX                      128
+
+/******************/
+/* NLSF quantizer */
+/******************/
+#define NLSF_W_Q                                2
+#define NLSF_VQ_MAX_VECTORS                     32
+#define NLSF_QUANT_MAX_AMPLITUDE                4
+#define NLSF_QUANT_MAX_AMPLITUDE_EXT            10
+#define NLSF_QUANT_LEVEL_ADJ                    0.1
+#define NLSF_QUANT_DEL_DEC_STATES_LOG2          2
+#define NLSF_QUANT_DEL_DEC_STATES               ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 )
+
+/* Transition filtering for mode switching */
+#define TRANSITION_TIME_MS                      5120    /* 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)*/
+#define TRANSITION_NB                           3       /* Hardcoded in tables */
+#define TRANSITION_NA                           2       /* Hardcoded in tables */
+#define TRANSITION_INT_NUM                      5       /* Hardcoded in tables */
+#define TRANSITION_FRAMES                       ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS )
+#define TRANSITION_INT_STEPS                    ( TRANSITION_FRAMES  / ( TRANSITION_INT_NUM - 1 ) )
+
+/* BWE factors to apply after packet loss */
+#define BWE_AFTER_LOSS_Q16                      63570
+
+/* Defines for CN generation */
+#define CNG_BUF_MASK_MAX                        255     /* 2^floor(log2(MAX_FRAME_LENGTH))-1    */
+#define CNG_GAIN_SMTH_Q16                       4634    /* 0.25^(1/4)                           */
+#define CNG_GAIN_SMTH_THRESHOLD_Q16             46396   /* -3 dB                                */
+#define CNG_NLSF_SMTH_Q16                       16348   /* 0.25                                 */
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/errors.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/errors.h
new file mode 100644 (file)
index 0000000..28b87dd
--- /dev/null
@@ -0,0 +1,90 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_ERRORS_H
+#define SILK_ERRORS_H
+
+
+/******************/
+/* Error messages */
+/******************/
+#define SILK_NO_ERROR                               0
+
+/**************************/
+/* Encoder error messages */
+/**************************/
+
+/* Input length is not a multiple of 10 ms, or length is longer than the packet length */
+#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES        -101
+
+/* Sampling frequency not 8000, 12000 or 16000 Hertz */
+#define SILK_ENC_FS_NOT_SUPPORTED                   -102
+
+/* Packet size not 10, 20, 40, or 60 ms */
+#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED          -103
+
+/* Allocated payload buffer too short */
+#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT              -104
+
+/* Loss rate not between 0 and 100 percent */
+#define SILK_ENC_INVALID_LOSS_RATE                  -105
+
+/* Complexity setting not valid, use 0...10 */
+#define SILK_ENC_INVALID_COMPLEXITY_SETTING         -106
+
+/* Inband FEC setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_INBAND_FEC_SETTING         -107
+
+/* DTX setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_DTX_SETTING                -108
+
+/* CBR setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_CBR_SETTING                -109
+
+/* Internal encoder error */
+#define SILK_ENC_INTERNAL_ERROR                     -110
+
+/* Internal encoder error */
+#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR   -111
+
+/**************************/
+/* Decoder error messages */
+/**************************/
+
+/* Output sampling frequency lower than internal decoded sampling frequency */
+#define SILK_DEC_INVALID_SAMPLING_FREQUENCY         -200
+
+/* Payload size exceeded the maximum allowed 1024 bytes */
+#define SILK_DEC_PAYLOAD_TOO_LARGE                  -201
+
+/* Payload has bit errors */
+#define SILK_DEC_PAYLOAD_ERROR                      -202
+
+/* Payload has bit errors */
+#define SILK_DEC_INVALID_FRAME_SIZE                 -203
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_analysis_filter_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_analysis_filter_FLP.c
new file mode 100644 (file)
index 0000000..f7007c3
--- /dev/null
@@ -0,0 +1,248 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+
+/************************************************/
+/* LPC analysis filter                          */
+/* NB! State is kept internally and the         */
+/* filter always starts with zero state         */
+/* first Order output samples are set to zero   */
+/************************************************/
+
+/* 16th order LPC analysis filter, does not write first 16 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter16_FLP(
+          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
+    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
+    const silk_float                 s[],                /* I    Input signal                            */
+    const opus_int                   length              /* I    Length of input signal                  */
+)
+{
+    opus_int   ix;
+    silk_float LPC_pred;
+    const silk_float *s_ptr;
+
+    for( ix = 16; ix < length; ix++ ) {
+        s_ptr = &s[ix - 1];
+
+        /* short-term prediction */
+        LPC_pred = s_ptr[  0 ]  * PredCoef[ 0 ]  +
+                   s_ptr[ -1 ]  * PredCoef[ 1 ]  +
+                   s_ptr[ -2 ]  * PredCoef[ 2 ]  +
+                   s_ptr[ -3 ]  * PredCoef[ 3 ]  +
+                   s_ptr[ -4 ]  * PredCoef[ 4 ]  +
+                   s_ptr[ -5 ]  * PredCoef[ 5 ]  +
+                   s_ptr[ -6 ]  * PredCoef[ 6 ]  +
+                   s_ptr[ -7 ]  * PredCoef[ 7 ]  +
+                   s_ptr[ -8 ]  * PredCoef[ 8 ]  +
+                   s_ptr[ -9 ]  * PredCoef[ 9 ]  +
+                   s_ptr[ -10 ] * PredCoef[ 10 ] +
+                   s_ptr[ -11 ] * PredCoef[ 11 ] +
+                   s_ptr[ -12 ] * PredCoef[ 12 ] +
+                   s_ptr[ -13 ] * PredCoef[ 13 ] +
+                   s_ptr[ -14 ] * PredCoef[ 14 ] +
+                   s_ptr[ -15 ] * PredCoef[ 15 ];
+
+        /* prediction error */
+        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+    }
+}
+
+/* 12th order LPC analysis filter, does not write first 12 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter12_FLP(
+          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
+    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
+    const silk_float                 s[],                /* I    Input signal                            */
+    const opus_int                   length              /* I    Length of input signal                  */
+)
+{
+    opus_int   ix;
+    silk_float LPC_pred;
+    const silk_float *s_ptr;
+
+    for( ix = 12; ix < length; ix++ ) {
+        s_ptr = &s[ix - 1];
+
+        /* short-term prediction */
+        LPC_pred = s_ptr[  0 ]  * PredCoef[ 0 ]  +
+                   s_ptr[ -1 ]  * PredCoef[ 1 ]  +
+                   s_ptr[ -2 ]  * PredCoef[ 2 ]  +
+                   s_ptr[ -3 ]  * PredCoef[ 3 ]  +
+                   s_ptr[ -4 ]  * PredCoef[ 4 ]  +
+                   s_ptr[ -5 ]  * PredCoef[ 5 ]  +
+                   s_ptr[ -6 ]  * PredCoef[ 6 ]  +
+                   s_ptr[ -7 ]  * PredCoef[ 7 ]  +
+                   s_ptr[ -8 ]  * PredCoef[ 8 ]  +
+                   s_ptr[ -9 ]  * PredCoef[ 9 ]  +
+                   s_ptr[ -10 ] * PredCoef[ 10 ] +
+                   s_ptr[ -11 ] * PredCoef[ 11 ];
+
+        /* prediction error */
+        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+    }
+}
+
+/* 10th order LPC analysis filter, does not write first 10 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter10_FLP(
+          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
+    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
+    const silk_float                 s[],                /* I    Input signal                            */
+    const opus_int                   length              /* I    Length of input signal                  */
+)
+{
+    opus_int   ix;
+    silk_float LPC_pred;
+    const silk_float *s_ptr;
+
+    for( ix = 10; ix < length; ix++ ) {
+        s_ptr = &s[ix - 1];
+
+        /* short-term prediction */
+        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
+                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
+                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
+                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
+                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
+                   s_ptr[ -5 ] * PredCoef[ 5 ]  +
+                   s_ptr[ -6 ] * PredCoef[ 6 ]  +
+                   s_ptr[ -7 ] * PredCoef[ 7 ]  +
+                   s_ptr[ -8 ] * PredCoef[ 8 ]  +
+                   s_ptr[ -9 ] * PredCoef[ 9 ];
+
+        /* prediction error */
+        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+    }
+}
+
+/* 8th order LPC analysis filter, does not write first 8 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter8_FLP(
+          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
+    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
+    const silk_float                 s[],                /* I    Input signal                            */
+    const opus_int                   length              /* I    Length of input signal                  */
+)
+{
+    opus_int   ix;
+    silk_float LPC_pred;
+    const silk_float *s_ptr;
+
+    for( ix = 8; ix < length; ix++ ) {
+        s_ptr = &s[ix - 1];
+
+        /* short-term prediction */
+        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
+                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
+                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
+                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
+                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
+                   s_ptr[ -5 ] * PredCoef[ 5 ]  +
+                   s_ptr[ -6 ] * PredCoef[ 6 ]  +
+                   s_ptr[ -7 ] * PredCoef[ 7 ];
+
+        /* prediction error */
+        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+    }
+}
+
+/* 6th order LPC analysis filter, does not write first 6 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter6_FLP(
+          silk_float                 r_LPC[],            /* O    LPC residual signal                     */
+    const silk_float                 PredCoef[],         /* I    LPC coefficients                        */
+    const silk_float                 s[],                /* I    Input signal                            */
+    const opus_int                   length              /* I    Length of input signal                  */
+)
+{
+    opus_int   ix;
+    silk_float LPC_pred;
+    const silk_float *s_ptr;
+
+    for( ix = 6; ix < length; ix++ ) {
+        s_ptr = &s[ix - 1];
+
+        /* short-term prediction */
+        LPC_pred = s_ptr[  0 ] * PredCoef[ 0 ]  +
+                   s_ptr[ -1 ] * PredCoef[ 1 ]  +
+                   s_ptr[ -2 ] * PredCoef[ 2 ]  +
+                   s_ptr[ -3 ] * PredCoef[ 3 ]  +
+                   s_ptr[ -4 ] * PredCoef[ 4 ]  +
+                   s_ptr[ -5 ] * PredCoef[ 5 ];
+
+        /* prediction error */
+        r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+    }
+}
+
+/************************************************/
+/* LPC analysis filter                          */
+/* NB! State is kept internally and the         */
+/* filter always starts with zero state         */
+/* first Order output samples are set to zero   */
+/************************************************/
+void silk_LPC_analysis_filter_FLP(
+    silk_float                      r_LPC[],                            /* O    LPC residual signal                         */
+    const silk_float                PredCoef[],                         /* I    LPC coefficients                            */
+    const silk_float                s[],                                /* I    Input signal                                */
+    const opus_int                  length,                             /* I    Length of input signal                      */
+    const opus_int                  Order                               /* I    LPC order                                   */
+)
+{
+    celt_assert( Order <= length );
+
+    switch( Order ) {
+        case 6:
+            silk_LPC_analysis_filter6_FLP(  r_LPC, PredCoef, s, length );
+        break;
+
+        case 8:
+            silk_LPC_analysis_filter8_FLP(  r_LPC, PredCoef, s, length );
+        break;
+
+        case 10:
+            silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length );
+        break;
+
+        case 12:
+            silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length );
+        break;
+
+        case 16:
+            silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length );
+        break;
+
+        default:
+            celt_assert( 0 );
+        break;
+    }
+
+    /* Set first Order output samples to zero */
+    silk_memset( r_LPC, 0, Order * sizeof( silk_float ) );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_inv_pred_gain_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LPC_inv_pred_gain_FLP.c
new file mode 100644 (file)
index 0000000..2be2122
--- /dev/null
@@ -0,0 +1,73 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "SigProc_FLP.h"
+#include "define.h"
+
+/* compute inverse of LPC prediction gain, and                          */
+/* test if LPC coefficients are stable (all poles within unit circle)   */
+/* this code is based on silk_a2k_FLP()                                 */
+silk_float silk_LPC_inverse_pred_gain_FLP(  /* O    return inverse prediction gain, energy domain               */
+    const silk_float    *A,                 /* I    prediction coefficients [order]                             */
+    opus_int32          order               /* I    prediction order                                            */
+)
+{
+    opus_int   k, n;
+    double     invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
+    silk_float Atmp[ SILK_MAX_ORDER_LPC ];
+
+    silk_memcpy( Atmp, A, order * sizeof(silk_float) );
+
+    invGain = 1.0;
+    for( k = order - 1; k > 0; k-- ) {
+        rc = -Atmp[ k ];
+        rc_mult1 = 1.0f - rc * rc;
+        invGain *= rc_mult1;
+        if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+            return 0.0f;
+        }
+        rc_mult2 = 1.0f / rc_mult1;
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = Atmp[ n ];
+            tmp2 = Atmp[ k - n - 1 ];
+            Atmp[ n ]         = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
+            Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
+        }
+    }
+    rc = -Atmp[ 0 ];
+    rc_mult1 = 1.0f - rc * rc;
+    invGain *= rc_mult1;
+    if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+        return 0.0f;
+    }
+    return (silk_float)invGain;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_analysis_filter_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_analysis_filter_FLP.c
new file mode 100644 (file)
index 0000000..849b7c1
--- /dev/null
@@ -0,0 +1,75 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+void silk_LTP_analysis_filter_FLP(
+    silk_float                      *LTP_res,                           /* O    LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */
+    const silk_float                *x,                                 /* I    Input signal, with preceding samples        */
+    const silk_float                B[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    LTP coefficients for each subframe          */
+    const opus_int                  pitchL[   MAX_NB_SUBFR ],           /* I    Pitch lags                                  */
+    const silk_float                invGains[ MAX_NB_SUBFR ],           /* I    Inverse quantization gains                  */
+    const opus_int                  subfr_length,                       /* I    Length of each subframe                     */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    const opus_int                  pre_length                          /* I    Preceding samples for each subframe         */
+)
+{
+    const silk_float *x_ptr, *x_lag_ptr;
+    silk_float   Btmp[ LTP_ORDER ];
+    silk_float   *LTP_res_ptr;
+    silk_float   inv_gain;
+    opus_int     k, i, j;
+
+    x_ptr = x;
+    LTP_res_ptr = LTP_res;
+    for( k = 0; k < nb_subfr; k++ ) {
+        x_lag_ptr = x_ptr - pitchL[ k ];
+        inv_gain = invGains[ k ];
+        for( i = 0; i < LTP_ORDER; i++ ) {
+            Btmp[ i ] = B[ k * LTP_ORDER + i ];
+        }
+
+        /* LTP analysis FIR filter */
+        for( i = 0; i < subfr_length + pre_length; i++ ) {
+            LTP_res_ptr[ i ] = x_ptr[ i ];
+            /* Subtract long-term prediction */
+            for( j = 0; j < LTP_ORDER; j++ ) {
+                LTP_res_ptr[ i ] -= Btmp[ j ] * x_lag_ptr[ LTP_ORDER / 2 - j ];
+            }
+            LTP_res_ptr[ i ] *= inv_gain;
+            x_lag_ptr++;
+        }
+
+        /* Update pointers */
+        LTP_res_ptr += subfr_length + pre_length;
+        x_ptr       += subfr_length;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_scale_ctrl_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/LTP_scale_ctrl_FLP.c
new file mode 100644 (file)
index 0000000..6f30ff0
--- /dev/null
@@ -0,0 +1,58 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+void silk_LTP_scale_ctrl_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+)
+{
+    opus_int   round_loss;
+
+    if( condCoding == CODE_INDEPENDENTLY ) {
+        /* Only scale if first frame in packet */
+        round_loss = psEnc->sCmn.PacketLoss_perc * psEnc->sCmn.nFramesPerPacket;
+        if ( psEnc->sCmn.LBRR_flag ) {
+            /* LBRR reduces the effective loss. In practice, it does not square the loss because
+               losses aren't independent, but that still seems to work best. We also never go below 2%. */
+            round_loss = 2 + silk_SMULBB( round_loss, round_loss) / 100;
+        }
+        psEnc->sCmn.indices.LTP_scaleIndex = silk_SMULBB( psEncCtrl->LTPredCodGain, round_loss ) > silk_log2lin( 2900 - psEnc->sCmn.SNR_dB_Q7 );
+        psEnc->sCmn.indices.LTP_scaleIndex += silk_SMULBB( psEncCtrl->LTPredCodGain, round_loss ) > silk_log2lin( 3900 - psEnc->sCmn.SNR_dB_Q7 );
+    } else {
+        /* Default is minimum scaling */
+        psEnc->sCmn.indices.LTP_scaleIndex = 0;
+    }
+
+    psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/apply_sine_window_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/apply_sine_window_FLP.c
new file mode 100644 (file)
index 0000000..e49e717
--- /dev/null
@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Apply sine window to signal vector   */
+/* Window types:                        */
+/*  1 -> sine window from 0 to pi/2     */
+/*  2 -> sine window from pi/2 to pi    */
+void silk_apply_sine_window_FLP(
+    silk_float                      px_win[],                           /* O    Pointer to windowed signal                  */
+    const silk_float                px[],                               /* I    Pointer to input signal                     */
+    const opus_int                  win_type,                           /* I    Selects a window type                       */
+    const opus_int                  length                              /* I    Window length, multiple of 4                */
+)
+{
+    opus_int   k;
+    silk_float freq, c, S0, S1;
+
+    celt_assert( win_type == 1 || win_type == 2 );
+
+    /* Length must be multiple of 4 */
+    celt_assert( ( length & 3 ) == 0 );
+
+    freq = PI / ( length + 1 );
+
+    /* Approximation of 2 * cos(f) */
+    c = 2.0f - freq * freq;
+
+    /* Initialize state */
+    if( win_type < 2 ) {
+        /* Start from 0 */
+        S0 = 0.0f;
+        /* Approximation of sin(f) */
+        S1 = freq;
+    } else {
+        /* Start from 1 */
+        S0 = 1.0f;
+        /* Approximation of cos(f) */
+        S1 = 0.5f * c;
+    }
+
+    /* Uses the recursive equation:   sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f)   */
+    /* 4 samples at a time */
+    for( k = 0; k < length; k += 4 ) {
+        px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 );
+        px_win[ k + 1 ] = px[ k + 1 ] * S1;
+        S0 = c * S1 - S0;
+        px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 );
+        px_win[ k + 3 ] = px[ k + 3 ] * S0;
+        S1 = c * S0 - S1;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/autocorrelation_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/autocorrelation_FLP.c
new file mode 100644 (file)
index 0000000..4253b26
--- /dev/null
@@ -0,0 +1,53 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "typedef.h"
+#include "SigProc_FLP.h"
+
+/* compute autocorrelation */
+void silk_autocorrelation_FLP(
+    silk_float          *results,           /* O    result (length correlationCount)                            */
+    const silk_float    *inputData,         /* I    input data to correlate                                     */
+    opus_int            inputDataSize,      /* I    length of input                                             */
+    opus_int            correlationCount,    /* I    number of correlation taps to compute                       */
+    int                 arch
+)
+{
+    opus_int i;
+
+    if( correlationCount > inputDataSize ) {
+        correlationCount = inputDataSize;
+    }
+
+    for( i = 0; i < correlationCount; i++ ) {
+        results[ i ] =  (silk_float)silk_inner_product_FLP( inputData, inputData + i, inputDataSize - i, arch );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/burg_modified_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/burg_modified_FLP.c
new file mode 100644 (file)
index 0000000..f5bef5d
--- /dev/null
@@ -0,0 +1,187 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+#include "tuning_parameters.h"
+#include "define.h"
+
+#define MAX_FRAME_SIZE              384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/
+
+/* Compute reflection coefficients from input signal */
+silk_float silk_burg_modified_FLP(          /* O    returns residual energy                                     */
+    silk_float          A[],                /* O    prediction coefficients (length order)                      */
+    const silk_float    x[],                /* I    input signal, length: nb_subfr*(D+L_sub)                    */
+    const silk_float    minInvGain,         /* I    minimum inverse prediction gain                             */
+    const opus_int      subfr_length,       /* I    input signal subframe length (incl. D preceding samples)    */
+    const opus_int      nb_subfr,           /* I    number of subframes stacked in x                            */
+    const opus_int      D,                  /* I    order                                                       */
+    int                 arch
+)
+{
+    opus_int         k, n, s, reached_max_gain;
+    double           C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2;
+    const silk_float *x_ptr;
+    double           C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ];
+    double           CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
+    double           Af[ SILK_MAX_ORDER_LPC ];
+
+    celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+
+    /* Compute autocorrelations, added over subframes */
+    C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
+    silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( double ) );
+    for( s = 0; s < nb_subfr; s++ ) {
+        x_ptr = x + s * subfr_length;
+        for( n = 1; n < D + 1; n++ ) {
+            C_first_row[ n - 1 ] += silk_inner_product_FLP( x_ptr, x_ptr + n, subfr_length - n, arch );
+        }
+    }
+    silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) );
+
+    /* Initialize */
+    CAb[ 0 ] = CAf[ 0 ] = C0 + FIND_LPC_COND_FAC * C0 + 1e-9f;
+    invGain = 1.0f;
+    reached_max_gain = 0;
+    for( n = 0; n < D; n++ ) {
+        /* Update first row of correlation matrix (without first element) */
+        /* Update last row of correlation matrix (without last element, stored in reversed order) */
+        /* Update C * Af */
+        /* Update C * flipud(Af) (stored in reversed order) */
+        for( s = 0; s < nb_subfr; s++ ) {
+            x_ptr = x + s * subfr_length;
+            tmp1 = x_ptr[ n ];
+            tmp2 = x_ptr[ subfr_length - n - 1 ];
+            for( k = 0; k < n; k++ ) {
+                C_first_row[ k ] -= x_ptr[ n ] * x_ptr[ n - k - 1 ];
+                C_last_row[ k ]  -= x_ptr[ subfr_length - n - 1 ] * x_ptr[ subfr_length - n + k ];
+                Atmp = Af[ k ];
+                tmp1 += x_ptr[ n - k - 1 ] * Atmp;
+                tmp2 += x_ptr[ subfr_length - n + k ] * Atmp;
+            }
+            for( k = 0; k <= n; k++ ) {
+                CAf[ k ] -= tmp1 * x_ptr[ n - k ];
+                CAb[ k ] -= tmp2 * x_ptr[ subfr_length - n + k - 1 ];
+            }
+        }
+        tmp1 = C_first_row[ n ];
+        tmp2 = C_last_row[ n ];
+        for( k = 0; k < n; k++ ) {
+            Atmp = Af[ k ];
+            tmp1 += C_last_row[  n - k - 1 ] * Atmp;
+            tmp2 += C_first_row[ n - k - 1 ] * Atmp;
+        }
+        CAf[ n + 1 ] = tmp1;
+        CAb[ n + 1 ] = tmp2;
+
+        /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
+        num = CAb[ n + 1 ];
+        nrg_b = CAb[ 0 ];
+        nrg_f = CAf[ 0 ];
+        for( k = 0; k < n; k++ ) {
+            Atmp = Af[ k ];
+            num   += CAb[ n - k ] * Atmp;
+            nrg_b += CAb[ k + 1 ] * Atmp;
+            nrg_f += CAf[ k + 1 ] * Atmp;
+        }
+        silk_assert( nrg_f > 0.0 );
+        silk_assert( nrg_b > 0.0 );
+
+        /* Calculate the next order reflection (parcor) coefficient */
+        rc = -2.0 * num / ( nrg_f + nrg_b );
+        silk_assert( rc > -1.0 && rc < 1.0 );
+
+        /* Update inverse prediction gain */
+        tmp1 = invGain * ( 1.0 - rc * rc );
+        if( tmp1 <= minInvGain ) {
+            /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */
+            rc = sqrt( 1.0 - minInvGain / invGain );
+            if( num > 0 ) {
+                /* Ensure adjusted reflection coefficients has the original sign */
+                rc = -rc;
+            }
+            invGain = minInvGain;
+            reached_max_gain = 1;
+        } else {
+            invGain = tmp1;
+        }
+
+        /* Update the AR coefficients */
+        for( k = 0; k < (n + 1) >> 1; k++ ) {
+            tmp1 = Af[ k ];
+            tmp2 = Af[ n - k - 1 ];
+            Af[ k ]         = tmp1 + rc * tmp2;
+            Af[ n - k - 1 ] = tmp2 + rc * tmp1;
+        }
+        Af[ n ] = rc;
+
+        if( reached_max_gain ) {
+            /* Reached max prediction gain; set remaining coefficients to zero and exit loop */
+            for( k = n + 1; k < D; k++ ) {
+                Af[ k ] = 0.0;
+            }
+            break;
+        }
+
+        /* Update C * Af and C * Ab */
+        for( k = 0; k <= n + 1; k++ ) {
+            tmp1 = CAf[ k ];
+            CAf[ k ]          += rc * CAb[ n - k + 1 ];
+            CAb[ n - k + 1  ] += rc * tmp1;
+        }
+    }
+
+    if( reached_max_gain ) {
+        /* Convert to silk_float */
+        for( k = 0; k < D; k++ ) {
+            A[ k ] = (silk_float)( -Af[ k ] );
+        }
+        /* Subtract energy of preceding samples from C0 */
+        for( s = 0; s < nb_subfr; s++ ) {
+            C0 -= silk_energy_FLP( x + s * subfr_length, D );
+        }
+        /* Approximate residual energy */
+        nrg_f = C0 * invGain;
+    } else {
+        /* Compute residual energy and store coefficients as silk_float */
+        nrg_f = CAf[ 0 ];
+        tmp1 = 1.0;
+        for( k = 0; k < D; k++ ) {
+            Atmp = Af[ k ];
+            nrg_f += CAf[ k + 1 ] * Atmp;
+            tmp1  += Atmp * Atmp;
+            A[ k ] = (silk_float)(-Atmp);
+        }
+        nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1;
+    }
+
+    /* Return residual energy */
+    return (silk_float)nrg_f;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/bwexpander_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/bwexpander_FLP.c
new file mode 100644 (file)
index 0000000..d55a4d7
--- /dev/null
@@ -0,0 +1,49 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* Chirp (bw expand) LP AR filter */
+void silk_bwexpander_FLP(
+    silk_float          *ar,                /* I/O  AR filter to be expanded (without leading 1)                */
+    const opus_int      d,                  /* I    length of ar                                                */
+    const silk_float    chirp               /* I    chirp factor (typically in range (0..1) )                   */
+)
+{
+    opus_int   i;
+    silk_float cfac = chirp;
+
+    for( i = 0; i < d - 1; i++ ) {
+        ar[ i ] *=  cfac;
+        cfac    *=  chirp;
+    }
+    ar[ d - 1 ] *=  cfac;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/corrMatrix_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/corrMatrix_FLP.c
new file mode 100644 (file)
index 0000000..eef6e8a
--- /dev/null
@@ -0,0 +1,95 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/**********************************************************************
+ * Correlation matrix computations for LS estimate.
+ **********************************************************************/
+
+#include "main_FLP.h"
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FLP(
+    const silk_float                *x,                                 /* I    x vector [L+order-1] used to create X       */
+    const silk_float                *t,                                 /* I    Target vector [L]                           */
+    const opus_int                  L,                                  /* I    Length of vecors                            */
+    const opus_int                  Order,                              /* I    Max lag for correlation                     */
+    silk_float                      *Xt,                                /* O    X'*t correlation vector [order]             */
+    int                             arch
+)
+{
+    opus_int lag;
+    const silk_float *ptr1;
+
+    ptr1 = &x[ Order - 1 ];                     /* Points to first sample of column 0 of X: X[:,0] */
+    for( lag = 0; lag < Order; lag++ ) {
+        /* Calculate X[:,lag]'*t */
+        Xt[ lag ] = (silk_float)silk_inner_product_FLP( ptr1, t, L, arch );
+        ptr1--;                                 /* Next column of X */
+    }
+}
+
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FLP(
+    const silk_float                *x,                                 /* I    x vector [ L+order-1 ] used to create X     */
+    const opus_int                  L,                                  /* I    Length of vectors                           */
+    const opus_int                  Order,                              /* I    Max lag for correlation                     */
+    silk_float                      *XX,                                /* O    X'*X correlation matrix [order x order]     */
+    int                             arch
+)
+{
+    opus_int j, lag;
+    double  energy;
+    const silk_float *ptr1, *ptr2;
+
+    ptr1 = &x[ Order - 1 ];                     /* First sample of column 0 of X */
+    energy = silk_energy_FLP( ptr1, L );  /* X[:,0]'*X[:,0] */
+    matrix_ptr( XX, 0, 0, Order ) = ( silk_float )energy;
+    for( j = 1; j < Order; j++ ) {
+        /* Calculate X[:,j]'*X[:,j] */
+        energy += ptr1[ -j ] * ptr1[ -j ] - ptr1[ L - j ] * ptr1[ L - j ];
+        matrix_ptr( XX, j, j, Order ) = ( silk_float )energy;
+    }
+
+    ptr2 = &x[ Order - 2 ];                     /* First sample of column 1 of X */
+    for( lag = 1; lag < Order; lag++ ) {
+        /* Calculate X[:,0]'*X[:,lag] */
+        energy = silk_inner_product_FLP( ptr1, ptr2, L, arch );
+        matrix_ptr( XX, lag, 0, Order ) = ( silk_float )energy;
+        matrix_ptr( XX, 0, lag, Order ) = ( silk_float )energy;
+        /* Calculate X[:,j]'*X[:,j + lag] */
+        for( j = 1; j < ( Order - lag ); j++ ) {
+            energy += ptr1[ -j ] * ptr2[ -j ] - ptr1[ L - j ] * ptr2[ L - j ];
+            matrix_ptr( XX, lag + j, j, Order ) = ( silk_float )energy;
+            matrix_ptr( XX, j, lag + j, Order ) = ( silk_float )energy;
+        }
+        ptr2--;                                 /* Next column of X */
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/encode_frame_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/encode_frame_FLP.c
new file mode 100644 (file)
index 0000000..32e25a4
--- /dev/null
@@ -0,0 +1,447 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+#include "stack_alloc.h"
+
+/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */
+static OPUS_INLINE void silk_LBRR_encode_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                xfw[],                              /* I    Input signal                                */
+    opus_int                        condCoding                          /* I    The type of conditional coding used so far for this frame */
+);
+
+void silk_encode_do_VAD_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    opus_int                        activity                            /* I    Decision of Opus voice activity detector    */
+)
+{
+    const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
+    /****************************/
+    /* Voice Activity Detection */
+    /****************************/
+    silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+    /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+    if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+        psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+    }
+
+    /**************************************************/
+    /* Convert speech activity into VAD and DTX flags */
+    /**************************************************/
+    if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
+        psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
+        psEnc->sCmn.noSpeechCounter++;
+        if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
+            psEnc->sCmn.inDTX = 0;
+        } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
+            psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
+            psEnc->sCmn.inDTX           = 0;
+        }
+        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
+    } else {
+        psEnc->sCmn.noSpeechCounter    = 0;
+        psEnc->sCmn.inDTX              = 0;
+        psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
+        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
+    }
+}
+
+/****************/
+/* Encode frame */
+/****************/
+opus_int silk_encode_frame_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    opus_int32                      *pnBytesOut,                        /* O    Number of payload bytes;                    */
+    ec_enc                          *psRangeEnc,                        /* I/O  compressor data structure                   */
+    opus_int                        condCoding,                         /* I    The type of conditional coding to use       */
+    opus_int                        maxBits,                            /* I    If > 0: maximum number of output bits       */
+    opus_int                        useCBR                              /* I    Flag to force constant-bitrate operation    */
+)
+{
+    silk_encoder_control_FLP sEncCtrl;
+    opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
+    silk_float   *x_frame, *res_pitch_frame;
+    silk_float   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
+    ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
+    VARDECL(silk_nsq_state, sNSQ_copy);
+    opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
+    opus_int32   gainsID, gainsID_lower, gainsID_upper;
+    opus_int16   gainMult_Q8;
+    opus_int16   ec_prevLagIndex_copy;
+    opus_int     ec_prevSignalType_copy;
+    opus_int8    LastGainIndex_copy2;
+    opus_int32   pGains_Q16[ MAX_NB_SUBFR ];
+    opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
+    opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
+    opus_int     best_sum[ MAX_NB_SUBFR ];
+    opus_int     bits_margin;
+    SAVE_STACK;
+
+    /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+       This is useful on some embedded systems. */
+    ALLOC(sNSQ_copy, 2, silk_nsq_state);
+
+    /* For CBR, 5 bits below budget is close enough. For VBR, allow up to 25% below the cap if we initially busted the budget. */
+    bits_margin = useCBR ? 5 : maxBits/4;
+    /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
+    LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
+
+    psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
+
+    /**************************************************************/
+    /* Set up Input Pointers, and insert frame in input buffer    */
+    /**************************************************************/
+    /* pointers aligned with start of frame to encode */
+    x_frame         = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;    /* start of frame to encode */
+    res_pitch_frame = res_pitch    + psEnc->sCmn.ltp_mem_length;    /* start of pitch LPC residual frame */
+
+    /***************************************/
+    /* Ensure smooth bandwidth transitions */
+    /***************************************/
+    silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
+
+    /*******************************************/
+    /* Copy new frame to front of input buffer */
+    /*******************************************/
+    silk_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
+
+    /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */
+    for( i = 0; i < 8; i++ ) {
+        x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f;
+    }
+
+    if( !psEnc->sCmn.prefillFlag ) {
+        VARDECL( opus_uint8, ec_buf_copy );
+        /*****************************************/
+        /* Find pitch lags, initial LPC analysis */
+        /*****************************************/
+        silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
+
+        /************************/
+        /* Noise shape analysis */
+        /************************/
+        silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame );
+
+        /***************************************************/
+        /* Find linear prediction coefficients (LPC + LTP) */
+        /***************************************************/
+        silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
+
+        /****************************************/
+        /* Process gains                        */
+        /****************************************/
+        silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
+
+        /****************************************/
+        /* Low Bitrate Redundant Encoding       */
+        /****************************************/
+        silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
+
+        /* Loop over quantizer and entroy coding to control bitrate */
+        maxIter = 6;
+        gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
+        found_lower = 0;
+        found_upper = 0;
+        gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
+        gainsID_lower = -1;
+        gainsID_upper = -1;
+        /* Copy part of the input state */
+        silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
+        silk_memcpy( &sNSQ_copy[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+        seed_copy = psEnc->sCmn.indices.Seed;
+        ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
+        ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
+        ALLOC( ec_buf_copy, 1275, opus_uint8 );
+        for( iter = 0; ; iter++ ) {
+            if( gainsID == gainsID_lower ) {
+                nBits = nBits_lower;
+            } else if( gainsID == gainsID_upper ) {
+                nBits = nBits_upper;
+            } else {
+                /* Restore part of the input state */
+                if( iter > 0 ) {
+                    silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
+                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[0], sizeof( silk_nsq_state ) );
+                    psEnc->sCmn.indices.Seed = seed_copy;
+                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+                }
+
+                /*****************************************/
+                /* Noise shaping quantization            */
+                /*****************************************/
+                silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
+
+                if ( iter == maxIter && !found_lower ) {
+                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+                }
+
+                /****************************************/
+                /* Encode Parameters                    */
+                /****************************************/
+                silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+                /****************************************/
+                /* Encode Excitation Signal             */
+                /****************************************/
+                silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+                      psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+                nBits = ec_tell( psRangeEnc );
+
+                /* If we still bust after the last iteration, do some damage control. */
+                if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+                    /* Keep gains the same as the last frame. */
+                    psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+                    for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                        psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+                    }
+                    if (condCoding != CODE_CONDITIONALLY) {
+                       psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+                    }
+                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+                    /* Clear all pulses. */
+                    for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+                        psEnc->sCmn.pulses[ i ] = 0;
+                    }
+
+                    silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+                    silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+                        psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+                    nBits = ec_tell( psRangeEnc );
+                }
+
+                if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
+                    break;
+                }
+            }
+
+            if( iter == maxIter ) {
+                if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
+                    /* Restore output state from earlier iteration that did meet the bitrate budget */
+                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+                    celt_assert( sRangeEnc_copy2.offs <= 1275 );
+                    silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
+                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[1], sizeof( silk_nsq_state ) );
+                    psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
+                }
+                break;
+            }
+
+            if( nBits > maxBits ) {
+                if( found_lower == 0 && iter >= 2 ) {
+                    /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
+                    sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
+                    /* Reducing dithering can help us hit the target. */
+                    psEnc->sCmn.indices.quantOffsetType = 0;
+                    found_upper = 0;
+                    gainsID_upper = -1;
+                } else {
+                    found_upper = 1;
+                    nBits_upper = nBits;
+                    gainMult_upper = gainMult_Q8;
+                    gainsID_upper = gainsID;
+                }
+            } else if( nBits < maxBits - bits_margin ) {
+                found_lower = 1;
+                nBits_lower = nBits;
+                gainMult_lower = gainMult_Q8;
+                if( gainsID != gainsID_lower ) {
+                    gainsID_lower = gainsID;
+                    /* Copy part of the output state */
+                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+                    celt_assert( psRangeEnc->offs <= 1275 );
+                    silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
+                    silk_memcpy( &sNSQ_copy[1], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+                    LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
+                }
+            } else {
+                /* Close enough */
+                break;
+            }
+
+            if ( !found_lower && nBits > maxBits ) {
+                int j;
+                for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                    int sum=0;
+                    for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+                        sum += abs( psEnc->sCmn.pulses[j] );
+                    }
+                    if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+                        best_sum[i] = sum;
+                        best_gain_mult[i] = gainMult_Q8;
+                    } else {
+                        gain_lock[i] = 1;
+                    }
+                }
+            }
+            if( ( found_lower & found_upper ) == 0 ) {
+                /* Adjust gain according to high-rate rate/distortion curve */
+                if( nBits > maxBits ) {
+                    gainMult_Q8 = silk_min_32( 1024, gainMult_Q8*3/2 );
+                } else {
+                    gainMult_Q8 = silk_max_32( 64, gainMult_Q8*4/5 );
+                }
+            } else {
+                /* Adjust gain by interpolating */
+                gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
+                /* New gain multiplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
+                if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
+                    gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
+                } else
+                if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
+                    gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
+                }
+            }
+
+            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                opus_int16 tmp;
+                if ( gain_lock[i] ) {
+                    tmp = best_gain_mult[i];
+                } else {
+                    tmp = gainMult_Q8;
+                }
+                pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
+            }
+
+            /* Quantize gains */
+            psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+            silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
+                  &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+            /* Unique identifier of gains vector */
+            gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
+
+            /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f;
+            }
+        }
+    }
+
+    /* Update input buffer */
+    silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
+        ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) );
+
+    /* Exit without entropy coding */
+    if( psEnc->sCmn.prefillFlag ) {
+        /* No payload */
+        *pnBytesOut = 0;
+        RESTORE_STACK;
+        return ret;
+    }
+
+    /* Parameters needed for next frame */
+    psEnc->sCmn.prevLag        = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
+    psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
+
+    /****************************************/
+    /* Finalize payload                     */
+    /****************************************/
+    psEnc->sCmn.first_frame_after_reset = 0;
+    /* Payload size */
+    *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
+
+    RESTORE_STACK;
+    return ret;
+}
+
+/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate  */
+static OPUS_INLINE void silk_LBRR_encode_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                xfw[],                              /* I    Input signal                                */
+    opus_int                        condCoding                          /* I    The type of conditional coding used so far for this frame */
+)
+{
+    opus_int     k;
+    opus_int32   Gains_Q16[ MAX_NB_SUBFR ];
+    silk_float   TempGains[ MAX_NB_SUBFR ];
+    SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
+    VARDECL(silk_nsq_state, sNSQ_LBRR);
+    SAVE_STACK;
+
+    /*******************************************/
+    /* Control use of inband LBRR              */
+    /*******************************************/
+    if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
+        /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+           This is useful on some embedded systems. */
+        ALLOC(sNSQ_LBRR, 1, silk_nsq_state);
+
+        psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
+
+        /* Copy noise shaping quantizer state and quantization indices from regular encoding */
+        silk_memcpy( &sNSQ_LBRR[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+        silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
+
+        /* Save original gains */
+        silk_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
+
+        if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
+            /* First frame in packet or previous frame not LBRR coded */
+            psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
+
+            /* Increase Gains to get target LBRR rate */
+            psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases;
+            psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
+        }
+
+        /* Decode to get gains in sync with decoder */
+        silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices,
+            &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+        /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+        for( k = 0; k <  psEnc->sCmn.nb_subfr; k++ ) {
+            psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f );
+        }
+
+        /*****************************************/
+        /* Noise shaping quantization            */
+        /*****************************************/
+        silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR[0],
+            psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw );
+
+        /* Restore original gains */
+        silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
+    }
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/energy_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/energy_FLP.c
new file mode 100644 (file)
index 0000000..7bc7173
--- /dev/null
@@ -0,0 +1,59 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* sum of squares of a silk_float array, with result as double */
+double silk_energy_FLP(
+    const silk_float    *data,
+    opus_int            dataSize
+)
+{
+    opus_int i;
+    double   result;
+
+    /* 4x unrolled loop */
+    result = 0.0;
+    for( i = 0; i < dataSize - 3; i += 4 ) {
+        result += data[ i + 0 ] * (double)data[ i + 0 ] +
+                  data[ i + 1 ] * (double)data[ i + 1 ] +
+                  data[ i + 2 ] * (double)data[ i + 2 ] +
+                  data[ i + 3 ] * (double)data[ i + 3 ];
+    }
+
+    /* add any remaining products */
+    for( ; i < dataSize; i++ ) {
+        result += data[ i ] * (double)data[ i ];
+    }
+
+    silk_assert( result >= 0.0 );
+    return result;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LPC_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LPC_FLP.c
new file mode 100644 (file)
index 0000000..6ccd711
--- /dev/null
@@ -0,0 +1,105 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "define.h"
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* LPC analysis */
+void silk_find_LPC_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
+    opus_int16                      NLSF_Q15[],                         /* O    NLSFs                                       */
+    const silk_float                x[],                                /* I    Input signal                                */
+    const silk_float                minInvGain,                         /* I    Inverse of max prediction gain              */
+    int                             arch
+)
+{
+    opus_int    k, subfr_length;
+    silk_float  a[ MAX_LPC_ORDER ];
+
+    /* Used only for NLSF interpolation */
+    silk_float  res_nrg, res_nrg_2nd, res_nrg_interp;
+    opus_int16  NLSF0_Q15[ MAX_LPC_ORDER ];
+    silk_float  a_tmp[ MAX_LPC_ORDER ];
+    silk_float  LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ];
+
+    subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
+
+    /* Default: No interpolation */
+    psEncC->indices.NLSFInterpCoef_Q2 = 4;
+
+    /* Burg AR analysis for the full frame */
+    res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, arch );
+
+    if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
+        /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than        */
+        /* adding it to the residual energy of the first 10 ms in each iteration of the search below    */
+        res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder, arch );
+
+        /* Convert to NLSFs */
+        silk_A2NLSF_FLP( NLSF_Q15, a_tmp, psEncC->predictLPCOrder );
+
+        /* Search over interpolation indices to find the one with lowest residual energy */
+        res_nrg_2nd = silk_float_MAX;
+        for( k = 3; k >= 0; k-- ) {
+            /* Interpolate NLSFs for first half */
+            silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
+
+            /* Convert to LPC for residual energy evaluation */
+            silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
+
+            /* Calculate residual energy with LSF interpolation */
+            silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
+            res_nrg_interp = (silk_float)(
+                silk_energy_FLP( LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder ) +
+                silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) );
+
+            /* Determine whether current interpolated NLSFs are best so far */
+            if( res_nrg_interp < res_nrg ) {
+                /* Interpolation has lower residual energy */
+                res_nrg = res_nrg_interp;
+                psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
+            } else if( res_nrg_interp > res_nrg_2nd ) {
+                /* No reason to continue iterating - residual energies will continue to climb */
+                break;
+            }
+            res_nrg_2nd = res_nrg_interp;
+        }
+    }
+
+    if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
+        /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
+        silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
+    }
+
+    celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
+        ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LTP_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_LTP_FLP.c
new file mode 100644 (file)
index 0000000..90aeeac
--- /dev/null
@@ -0,0 +1,65 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+void silk_find_LTP_FLP(
+    silk_float                      XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization         */
+    silk_float                      xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* O    Weight for LTP quantization                 */
+    const silk_float                r_ptr[],                            /* I    LPC residual                                */
+    const opus_int                  lag[ MAX_NB_SUBFR ],                /* I    LTP lags                                    */
+    const opus_int                  subfr_length,                       /* I    Subframe length                             */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    int                             arch
+)
+{
+    opus_int   k;
+    silk_float *xX_ptr, *XX_ptr;
+    const silk_float *lag_ptr;
+    silk_float xx, temp;
+
+    xX_ptr = xX;
+    XX_ptr = XX;
+    for( k = 0; k < nb_subfr; k++ ) {
+        lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
+        silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr, arch );
+        silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr, arch );
+        xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
+        temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
+        silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
+        silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
+
+        r_ptr  += subfr_length;
+        XX_ptr += LTP_ORDER * LTP_ORDER;
+        xX_ptr += LTP_ORDER;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pitch_lags_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pitch_lags_FLP.c
new file mode 100644 (file)
index 0000000..796a924
--- /dev/null
@@ -0,0 +1,132 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+void silk_find_pitch_lags_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    silk_float                      res[],                              /* O    Residual                                    */
+    const silk_float                x[],                                /* I    Speech signal                               */
+    int                             arch                                /* I    Run-time architecture                       */
+)
+{
+    opus_int   buf_len;
+    silk_float thrhld, res_nrg;
+    const silk_float *x_buf_ptr, *x_buf;
+    silk_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
+    silk_float A[         MAX_FIND_PITCH_LPC_ORDER ];
+    silk_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ];
+    silk_float Wsig[      FIND_PITCH_LPC_WIN_MAX ];
+    silk_float *Wsig_ptr;
+
+    /******************************************/
+    /* Set up buffer lengths etc based on Fs  */
+    /******************************************/
+    buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
+
+    /* Safety check */
+    celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+
+    x_buf = x - psEnc->sCmn.ltp_mem_length;
+
+    /******************************************/
+    /* Estimate LPC AR coefficients           */
+    /******************************************/
+
+    /* Calculate windowed signal */
+
+    /* First LA_LTP samples */
+    x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
+    Wsig_ptr  = Wsig;
+    silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
+
+    /* Middle non-windowed samples */
+    Wsig_ptr  += psEnc->sCmn.la_pitch;
+    x_buf_ptr += psEnc->sCmn.la_pitch;
+    silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( silk_float ) );
+
+    /* Last LA_LTP samples */
+    Wsig_ptr  += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 );
+    x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 );
+    silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
+
+    /* Calculate autocorrelation sequence */
+    silk_autocorrelation_FLP( auto_corr, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
+
+    /* Add white noise, as a fraction of the energy */
+    auto_corr[ 0 ] += auto_corr[ 0 ] * FIND_PITCH_WHITE_NOISE_FRACTION + 1;
+
+    /* Calculate the reflection coefficients using Schur */
+    res_nrg = silk_schur_FLP( refl_coef, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder );
+
+    /* Prediction gain */
+    psEncCtrl->predGain = auto_corr[ 0 ] / silk_max_float( res_nrg, 1.0f );
+
+    /* Convert reflection coefficients to prediction coefficients */
+    silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder );
+
+    /* Bandwidth expansion */
+    silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWIDTH_EXPANSION );
+
+    /*****************************************/
+    /* LPC analysis filtering                */
+    /*****************************************/
+    silk_LPC_analysis_filter_FLP( res, A, x_buf, buf_len, psEnc->sCmn.pitchEstimationLPCOrder );
+
+    if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
+        /* Threshold for pitch estimator */
+        thrhld  = 0.6f;
+        thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder;
+        thrhld -= 0.1f   * psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
+        thrhld -= 0.15f  * (psEnc->sCmn.prevSignalType >> 1);
+        thrhld -= 0.1f   * psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f );
+
+        /*****************************************/
+        /* Call Pitch estimator                  */
+        /*****************************************/
+        if( silk_pitch_analysis_core_FLP( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex,
+            &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f,
+            thrhld, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, arch ) == 0 )
+        {
+            psEnc->sCmn.indices.signalType = TYPE_VOICED;
+        } else {
+            psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
+        }
+    } else {
+        silk_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) );
+        psEnc->sCmn.indices.lagIndex = 0;
+        psEnc->sCmn.indices.contourIndex = 0;
+        psEnc->LTPCorr = 0;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pred_coefs_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/find_pred_coefs_FLP.c
new file mode 100644 (file)
index 0000000..01c2d34
--- /dev/null
@@ -0,0 +1,116 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                res_pitch[],                        /* I    Residual from pitch analysis                */
+    const silk_float                x[],                                /* I    Speech signal                               */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+)
+{
+    opus_int         i;
+    silk_float       XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+    silk_float       xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
+    silk_float       invGains[ MAX_NB_SUBFR ];
+    /* Set to NLSF_Q15 to zero so we don't copy junk to the state. */
+    opus_int16       NLSF_Q15[ MAX_LPC_ORDER ]={0};
+    const silk_float *x_ptr;
+    silk_float       *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
+    silk_float       minInvGain;
+
+    /* Weighting for weighted least squares */
+    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+        silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
+        invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
+    }
+
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        /**********/
+        /* VOICED */
+        /**********/
+        celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+
+        /* LTP analysis */
+        silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+
+        /* Quantize LTP gain parameters */
+        silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
+            &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+
+        /* Control LTP scaling */
+        silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
+
+        /* Create LTP residual */
+        silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef,
+            psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
+    } else {
+        /************/
+        /* UNVOICED */
+        /************/
+        /* Create signal with prepended subframes, scaled by inverse gains */
+        x_ptr     = x - psEnc->sCmn.predictLPCOrder;
+        x_pre_ptr = LPC_in_pre;
+        for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+            silk_scale_copy_vector_FLP( x_pre_ptr, x_ptr, invGains[ i ],
+                psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder );
+            x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder;
+            x_ptr     += psEnc->sCmn.subfr_length;
+        }
+        silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
+        psEncCtrl->LTPredCodGain = 0.0f;
+        psEnc->sCmn.sum_log_gain_Q7 = 0;
+    }
+
+    /* Limit on total predictive coding gain */
+    if( psEnc->sCmn.first_frame_after_reset ) {
+        minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET;
+    } else {
+        minInvGain = (silk_float)pow( 2, psEncCtrl->LTPredCodGain / 3 ) /  MAX_PREDICTION_POWER_GAIN;
+        minInvGain /= 0.25f + 0.75f * psEncCtrl->coding_quality;
+    }
+
+    /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
+    silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain, psEnc->sCmn.arch );
+
+    /* Quantize LSFs */
+    silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );
+
+    /* Calculate residual energy using quantized LPC coefficients */
+    silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains,
+        psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
+
+    /* Copy to prediction struct for use in next frame for interpolation */
+    silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP.c
new file mode 100644 (file)
index 0000000..88b160a
--- /dev/null
@@ -0,0 +1,59 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_c(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+)
+{
+    opus_int i;
+    double   result;
+
+    /* 4x unrolled loop */
+    result = 0.0;
+    for( i = 0; i < dataSize - 3; i += 4 ) {
+        result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
+                  data1[ i + 1 ] * (double)data2[ i + 1 ] +
+                  data1[ i + 2 ] * (double)data2[ i + 2 ] +
+                  data1[ i + 3 ] * (double)data2[ i + 3 ];
+    }
+
+    /* add any remaining products */
+    for( ; i < dataSize; i++ ) {
+        result += data1[ i ] * (double)data2[ i ];
+    }
+
+    return result;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP_avx2.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/inner_product_FLP_avx2.c
new file mode 100644 (file)
index 0000000..4a2daaf
--- /dev/null
@@ -0,0 +1,85 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+              2023 Amazon
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+#include <immintrin.h>
+
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_avx2(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+)
+{
+    opus_int i;
+    __m256d accum1, accum2;
+    double   result;
+
+    /* 4x unrolled loop */
+    result = 0.0;
+    accum1 = accum2 = _mm256_setzero_pd();
+    for( i = 0; i < dataSize - 7; i += 8 ) {
+        __m128  x1f, x2f;
+        __m256d x1d, x2d;
+        x1f = _mm_loadu_ps( &data1[ i ] );
+        x2f = _mm_loadu_ps( &data2[ i ] );
+        x1d = _mm256_cvtps_pd( x1f );
+        x2d = _mm256_cvtps_pd( x2f );
+        accum1 = _mm256_fmadd_pd( x1d, x2d, accum1 );
+        x1f = _mm_loadu_ps( &data1[ i + 4 ] );
+        x2f = _mm_loadu_ps( &data2[ i + 4 ] );
+        x1d = _mm256_cvtps_pd( x1f );
+        x2d = _mm256_cvtps_pd( x2f );
+        accum2 = _mm256_fmadd_pd( x1d, x2d, accum2 );
+    }
+    for( ; i < dataSize - 3; i += 4 ) {
+        __m128  x1f, x2f;
+        __m256d x1d, x2d;
+        x1f = _mm_loadu_ps( &data1[ i ] );
+        x2f = _mm_loadu_ps( &data2[ i ] );
+        x1d = _mm256_cvtps_pd( x1f );
+        x2d = _mm256_cvtps_pd( x2f );
+        accum1 = _mm256_fmadd_pd( x1d, x2d, accum1 );
+    }
+    accum1 = _mm256_add_pd(accum1, accum2);
+    accum1 = _mm256_add_pd(accum1, _mm256_permute2f128_pd(accum1, accum1, 1));
+    accum1 = _mm256_hadd_pd(accum1,accum1);
+    result = _mm256_cvtsd_f64(accum1);
+
+    /* add any remaining products */
+    for( ; i < dataSize; i++ ) {
+        result += data1[ i ] * (double)data2[ i ];
+    }
+
+    return result;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/k2a_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/k2a_FLP.c
new file mode 100644 (file)
index 0000000..1448008
--- /dev/null
@@ -0,0 +1,54 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a_FLP(
+    silk_float          *A,                 /* O     prediction coefficients [order]                            */
+    const silk_float    *rc,                /* I     reflection coefficients [order]                            */
+    opus_int32          order               /* I     prediction order                                           */
+)
+{
+    opus_int   k, n;
+    silk_float rck, tmp1, tmp2;
+
+    for( k = 0; k < order; k++ ) {
+        rck = rc[ k ];
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = A[ n ];
+            tmp2 = A[ k - n - 1 ];
+            A[ n ]         = tmp1 + tmp2 * rck;
+            A[ k - n - 1 ] = tmp2 + tmp1 * rck;
+        }
+        A[ k ] = -rck;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/noise_shape_analysis_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/noise_shape_analysis_FLP.c
new file mode 100644 (file)
index 0000000..0b5ea95
--- /dev/null
@@ -0,0 +1,350 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a   */
+/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
+/* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
+/* coefficient in an array of coefficients, for monic filters.                                    */
+static OPUS_INLINE silk_float warped_gain(
+    const silk_float     *coefs,
+    silk_float           lambda,
+    opus_int             order
+) {
+    opus_int   i;
+    silk_float gain;
+
+    lambda = -lambda;
+    gain = coefs[ order - 1 ];
+    for( i = order - 2; i >= 0; i-- ) {
+        gain = lambda * gain + coefs[ i ];
+    }
+    return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
+}
+
+/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum     */
+/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
+static OPUS_INLINE void warped_true2monic_coefs(
+    silk_float           *coefs,
+    silk_float           lambda,
+    silk_float           limit,
+    opus_int             order
+) {
+    opus_int   i, iter, ind = 0;
+    silk_float tmp, maxabs, chirp, gain;
+
+    /* Convert to monic coefficients */
+    for( i = order - 1; i > 0; i-- ) {
+        coefs[ i - 1 ] -= lambda * coefs[ i ];
+    }
+    gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+    for( i = 0; i < order; i++ ) {
+        coefs[ i ] *= gain;
+    }
+
+    /* Limit */
+    for( iter = 0; iter < 10; iter++ ) {
+        /* Find maximum absolute value */
+        maxabs = -1.0f;
+        for( i = 0; i < order; i++ ) {
+            tmp = silk_abs_float( coefs[ i ] );
+            if( tmp > maxabs ) {
+                maxabs = tmp;
+                ind = i;
+            }
+        }
+        if( maxabs <= limit ) {
+            /* Coefficients are within range - done */
+            return;
+        }
+
+        /* Convert back to true warped coefficients */
+        for( i = 1; i < order; i++ ) {
+            coefs[ i - 1 ] += lambda * coefs[ i ];
+        }
+        gain = 1.0f / gain;
+        for( i = 0; i < order; i++ ) {
+            coefs[ i ] *= gain;
+        }
+
+        /* Apply bandwidth expansion */
+        chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+        silk_bwexpander_FLP( coefs, order, chirp );
+
+        /* Convert to monic warped coefficients */
+        for( i = order - 1; i > 0; i-- ) {
+            coefs[ i - 1 ] -= lambda * coefs[ i ];
+        }
+        gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+        for( i = 0; i < order; i++ ) {
+            coefs[ i ] *= gain;
+        }
+    }
+    silk_assert( 0 );
+}
+
+static OPUS_INLINE void limit_coefs(
+    silk_float           *coefs,
+    silk_float           limit,
+    opus_int             order
+) {
+    opus_int   i, iter, ind = 0;
+    silk_float tmp, maxabs, chirp;
+
+    for( iter = 0; iter < 10; iter++ ) {
+        /* Find maximum absolute value */
+        maxabs = -1.0f;
+        for( i = 0; i < order; i++ ) {
+            tmp = silk_abs_float( coefs[ i ] );
+            if( tmp > maxabs ) {
+                maxabs = tmp;
+                ind = i;
+            }
+        }
+        if( maxabs <= limit ) {
+            /* Coefficients are within range - done */
+            return;
+        }
+
+        /* Apply bandwidth expansion */
+        chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+        silk_bwexpander_FLP( coefs, order, chirp );
+    }
+    silk_assert( 0 );
+}
+
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
+    const silk_float                *x                                  /* I    Input signal [frame_length + la_shape]      */
+)
+{
+    silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
+    opus_int     k, nSamples, nSegs;
+    silk_float   SNR_adj_dB, HarmShapeGain, Tilt;
+    silk_float   nrg, log_energy, log_energy_prev, energy_variation;
+    silk_float   BWExp, gain_mult, gain_add, strength, b, warping;
+    silk_float   x_windowed[ SHAPE_LPC_WIN_MAX ];
+    silk_float   auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
+    silk_float   rc[ MAX_SHAPE_LPC_ORDER + 1 ];
+    const silk_float *x_ptr, *pitch_res_ptr;
+
+    /* Point to start of first LPC analysis block */
+    x_ptr = x - psEnc->sCmn.la_shape;
+
+    /****************/
+    /* GAIN CONTROL */
+    /****************/
+    SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f );
+
+    /* Input quality is the average of the quality in the lowest two VAD bands */
+    psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
+
+    /* Coding quality level, between 0.0 and 1.0 */
+    psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
+
+    if( psEnc->sCmn.useCBR == 0 ) {
+        /* Reduce coding SNR during low speech activity */
+        b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
+        SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;
+    }
+
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        /* Reduce gains for periodic signals */
+        SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;
+    } else {
+        /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
+        SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );
+    }
+
+    /*************************/
+    /* SPARSENESS PROCESSING */
+    /*************************/
+    /* Set quantizer offset */
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        /* Initially set to 0; may be overruled in process_gains(..) */
+        psEnc->sCmn.indices.quantOffsetType = 0;
+    } else {
+        /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
+        nSamples = 2 * psEnc->sCmn.fs_kHz;
+        energy_variation = 0.0f;
+        log_energy_prev  = 0.0f;
+        pitch_res_ptr = pitch_res;
+        nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+        for( k = 0; k < nSegs; k++ ) {
+            nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
+            log_energy = silk_log2( nrg );
+            if( k > 0 ) {
+                energy_variation += silk_abs_float( log_energy - log_energy_prev );
+            }
+            log_energy_prev = log_energy;
+            pitch_res_ptr += nSamples;
+        }
+
+        /* Set quantization offset depending on sparseness measure */
+        if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
+            psEnc->sCmn.indices.quantOffsetType = 0;
+        } else {
+            psEnc->sCmn.indices.quantOffsetType = 1;
+        }
+    }
+
+    /*******************************/
+    /* Control bandwidth expansion */
+    /*******************************/
+    /* More BWE for signals with high prediction gain */
+    strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain;           /* between 0.0 and 1.0 */
+    BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
+
+    /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
+    warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
+
+    /********************************************/
+    /* Compute noise shaping AR coefs and gains */
+    /********************************************/
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        /* Apply window: sine slope followed by flat part followed by cosine slope */
+        opus_int shift, slope_part, flat_part;
+        flat_part = psEnc->sCmn.fs_kHz * 3;
+        slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2;
+
+        silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part );
+        shift = slope_part;
+        silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) );
+        shift += flat_part;
+        silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part );
+
+        /* Update pointer: next LPC analysis block */
+        x_ptr += psEnc->sCmn.subfr_length;
+
+        if( psEnc->sCmn.warping_Q16 > 0 ) {
+            /* Calculate warped auto correlation */
+            silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
+                psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+        } else {
+            /* Calculate regular auto correlation */
+            silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, psEnc->sCmn.arch );
+        }
+
+        /* Add white noise, as a fraction of energy */
+        auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
+
+        /* Convert correlations to prediction coefficients, and compute residual energy */
+        nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
+        silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
+        psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
+
+        if( psEnc->sCmn.warping_Q16 > 0 ) {
+            /* Adjust gain for warping */
+            psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
+        }
+
+        /* Bandwidth expansion for synthesis filter shaping */
+        silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
+
+        if( psEnc->sCmn.warping_Q16 > 0 ) {
+            /* Convert to monic warped prediction coefficients and limit absolute values */
+            warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+        } else {
+            /* Limit absolute values */
+            limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
+        }
+    }
+
+    /*****************/
+    /* Gain tweaking */
+    /*****************/
+    /* Increase gains during low speech activity */
+    gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
+    gain_add  = (silk_float)pow( 2.0f,  0.16f * MIN_QGAIN_DB );
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        psEncCtrl->Gains[ k ] *= gain_mult;
+        psEncCtrl->Gains[ k ] += gain_add;
+    }
+
+    /************************************************/
+    /* Control low-frequency shaping and noise tilt */
+    /************************************************/
+    /* Less low frequency shaping for noisy inputs */
+    strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) );
+    strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
+        /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
+        for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+            b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ];
+            psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;
+            psEncCtrl->LF_AR_shp[ k ] =  1.0f - b - b * strength;
+        }
+        Tilt = - HP_NOISE_COEF -
+            (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
+    } else {
+        b = 1.3f / psEnc->sCmn.fs_kHz;
+        psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;
+        psEncCtrl->LF_AR_shp[ 0 ] =  1.0f - b - b * strength * 0.6f;
+        for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
+            psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ];
+            psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
+        }
+        Tilt = -HP_NOISE_COEF;
+    }
+
+    /****************************/
+    /* HARMONIC SHAPING CONTROL */
+    /****************************/
+    if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        /* Harmonic noise shaping */
+        HarmShapeGain = HARMONIC_SHAPING;
+
+        /* More harmonic noise shaping for high bitrates or noisy input */
+        HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
+            ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
+
+        /* Less harmonic noise shaping for less periodic signals */
+        HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr );
+    } else {
+        HarmShapeGain = 0.0f;
+    }
+
+    /*************************/
+    /* Smooth over subframes */
+    /*************************/
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
+        psEncCtrl->HarmShapeGain[ k ]  = psShapeSt->HarmShapeGain_smth;
+        psShapeSt->Tilt_smth          += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
+        psEncCtrl->Tilt[ k ]           = psShapeSt->Tilt_smth;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/pitch_analysis_core_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/pitch_analysis_core_FLP.c
new file mode 100644 (file)
index 0000000..0530a88
--- /dev/null
@@ -0,0 +1,630 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*****************************************************************************
+* Pitch analyser function
+******************************************************************************/
+#include "SigProc_FLP.h"
+#include "SigProc_FIX.h"
+#include "pitch_est_defines.h"
+#include "pitch.h"
+
+#define SCRATCH_SIZE        22
+
+/************************************************************/
+/* Internally used functions                                */
+/************************************************************/
+static void silk_P_Ana_calc_corr_st3(
+    silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+    const silk_float    frame[],            /* I vector to correlate                                            */
+    opus_int            start_lag,          /* I start lag                                                      */
+    opus_int            sf_length,          /* I sub frame length                                               */
+    opus_int            nb_subfr,           /* I number of subframes                                            */
+    opus_int            complexity,         /* I Complexity setting                                             */
+    int                 arch                /* I Run-time architecture                                          */
+);
+
+static void silk_P_Ana_calc_energy_st3(
+    silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+    const silk_float    frame[],            /* I vector to correlate                                            */
+    opus_int            start_lag,          /* I start lag                                                      */
+    opus_int            sf_length,          /* I sub frame length                                               */
+    opus_int            nb_subfr,           /* I number of subframes                                            */
+    opus_int            complexity          /* I Complexity setting                                             */
+);
+
+/************************************************************/
+/* CORE PITCH ANALYSIS FUNCTION                             */
+/************************************************************/
+opus_int silk_pitch_analysis_core_FLP(      /* O    Voicing estimate: 0 voiced, 1 unvoiced                      */
+    const silk_float    *frame,             /* I    Signal of length PE_FRAME_LENGTH_MS*Fs_kHz                  */
+    opus_int            *pitch_out,         /* O    Pitch lag values [nb_subfr]                                 */
+    opus_int16          *lagIndex,          /* O    Lag Index                                                   */
+    opus_int8           *contourIndex,      /* O    Pitch contour Index                                         */
+    silk_float          *LTPCorr,           /* I/O  Normalized correlation; input: value from previous frame    */
+    opus_int            prevLag,            /* I    Last lag of previous frame; set to zero is unvoiced         */
+    const silk_float    search_thres1,      /* I    First stage threshold for lag candidates 0 - 1              */
+    const silk_float    search_thres2,      /* I    Final threshold for lag candidates 0 - 1                    */
+    const opus_int      Fs_kHz,             /* I    sample frequency (kHz)                                      */
+    const opus_int      complexity,         /* I    Complexity setting, 0-2, where 2 is highest                 */
+    const opus_int      nb_subfr,           /* I    Number of 5 ms subframes                                    */
+    int                 arch                /* I    Run-time architecture                                       */
+)
+{
+    opus_int   i, k, d, j;
+    silk_float frame_8kHz[  PE_MAX_FRAME_LENGTH_MS * 8 ];
+    silk_float frame_4kHz[  PE_MAX_FRAME_LENGTH_MS * 4 ];
+    opus_int16 frame_8_FIX[ PE_MAX_FRAME_LENGTH_MS * 8 ];
+    opus_int16 frame_4_FIX[ PE_MAX_FRAME_LENGTH_MS * 4 ];
+    opus_int32 filt_state[ 6 ];
+    silk_float threshold, contour_bias;
+    silk_float C[ PE_MAX_NB_SUBFR][ (PE_MAX_LAG >> 1) + 5 ];
+    opus_val32 xcorr[ PE_MAX_LAG_MS * 4 - PE_MIN_LAG_MS * 4 + 1 ];
+    silk_float CC[ PE_NB_CBKS_STAGE2_EXT ];
+    const silk_float *target_ptr, *basis_ptr;
+    double    cross_corr, normalizer, energy, energy_tmp;
+    opus_int   d_srch[ PE_D_SRCH_LENGTH ];
+    opus_int16 d_comp[ (PE_MAX_LAG >> 1) + 5 ];
+    opus_int   length_d_srch, length_d_comp;
+    silk_float Cmax, CCmax, CCmax_b, CCmax_new_b, CCmax_new;
+    opus_int   CBimax, CBimax_new, lag, start_lag, end_lag, lag_new;
+    opus_int   cbk_size;
+    silk_float lag_log2, prevLag_log2, delta_lag_log2_sqr;
+    silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
+    silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
+    opus_int   lag_counter;
+    opus_int   frame_length, frame_length_8kHz, frame_length_4kHz;
+    opus_int   sf_length, sf_length_8kHz, sf_length_4kHz;
+    opus_int   min_lag, min_lag_8kHz, min_lag_4kHz;
+    opus_int   max_lag, max_lag_8kHz, max_lag_4kHz;
+    opus_int   nb_cbk_search;
+    const opus_int8 *Lag_CB_ptr;
+
+    /* Check for valid sampling frequency */
+    celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+
+    /* Check for valid complexity setting */
+    celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+    celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+    silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
+    silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
+
+    /* Set up frame lengths max / min lag for the sampling frequency */
+    frame_length      = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
+    frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
+    frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
+    sf_length         = PE_SUBFR_LENGTH_MS * Fs_kHz;
+    sf_length_4kHz    = PE_SUBFR_LENGTH_MS * 4;
+    sf_length_8kHz    = PE_SUBFR_LENGTH_MS * 8;
+    min_lag           = PE_MIN_LAG_MS * Fs_kHz;
+    min_lag_4kHz      = PE_MIN_LAG_MS * 4;
+    min_lag_8kHz      = PE_MIN_LAG_MS * 8;
+    max_lag           = PE_MAX_LAG_MS * Fs_kHz - 1;
+    max_lag_4kHz      = PE_MAX_LAG_MS * 4;
+    max_lag_8kHz      = PE_MAX_LAG_MS * 8 - 1;
+
+    /* Resample from input sampled at Fs_kHz to 8 kHz */
+    if( Fs_kHz == 16 ) {
+        /* Resample to 16 -> 8 khz */
+        opus_int16 frame_16_FIX[ 16 * PE_MAX_FRAME_LENGTH_MS ];
+        silk_float2short_array( frame_16_FIX, frame, frame_length );
+        silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
+        silk_resampler_down2( filt_state, frame_8_FIX, frame_16_FIX, frame_length );
+        silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
+    } else if( Fs_kHz == 12 ) {
+        /* Resample to 12 -> 8 khz */
+        opus_int16 frame_12_FIX[ 12 * PE_MAX_FRAME_LENGTH_MS ];
+        silk_float2short_array( frame_12_FIX, frame, frame_length );
+        silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
+        silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
+        silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
+    } else {
+        celt_assert( Fs_kHz == 8 );
+        silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
+    }
+
+    /* Decimate again to 4 kHz */
+    silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
+    silk_resampler_down2( filt_state, frame_4_FIX, frame_8_FIX, frame_length_8kHz );
+    silk_short2float_array( frame_4kHz, frame_4_FIX, frame_length_4kHz );
+
+    /* Low-pass filter */
+    for( i = frame_length_4kHz - 1; i > 0; i-- ) {
+        frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
+    }
+
+    /******************************************************************************
+    * FIRST STAGE, operating in 4 khz
+    ******************************************************************************/
+    silk_memset(C, 0, sizeof(silk_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5));
+    target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
+    for( k = 0; k < nb_subfr >> 1; k++ ) {
+        /* Check that we are within range of the array */
+        celt_assert( target_ptr >= frame_4kHz );
+        celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+        basis_ptr = target_ptr - min_lag_4kHz;
+
+        /* Check that we are within range of the array */
+        celt_assert( basis_ptr >= frame_4kHz );
+        celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+        celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
+
+        /* Calculate first vector products before loop */
+        cross_corr = xcorr[ max_lag_4kHz - min_lag_4kHz ];
+        normalizer = silk_energy_FLP( target_ptr, sf_length_8kHz ) +
+                     silk_energy_FLP( basis_ptr,  sf_length_8kHz ) +
+                     sf_length_8kHz * 4000.0f;
+
+        C[ 0 ][ min_lag_4kHz ] += (silk_float)( 2 * cross_corr / normalizer );
+
+        /* From now on normalizer is computed recursively */
+        for( d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++ ) {
+            basis_ptr--;
+
+            /* Check that we are within range of the array */
+            silk_assert( basis_ptr >= frame_4kHz );
+            silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+            cross_corr = xcorr[ max_lag_4kHz - d ];
+
+            /* Add contribution of new sample and remove contribution from oldest sample */
+            normalizer +=
+                basis_ptr[ 0 ] * (double)basis_ptr[ 0 ] -
+                basis_ptr[ sf_length_8kHz ] * (double)basis_ptr[ sf_length_8kHz ];
+            C[ 0 ][ d ] += (silk_float)( 2 * cross_corr / normalizer );
+        }
+        /* Update target pointer */
+        target_ptr += sf_length_8kHz;
+    }
+
+    /* Apply short-lag bias */
+    for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) {
+        C[ 0 ][ i ] -= C[ 0 ][ i ] * i / 4096.0f;
+    }
+
+    /* Sort */
+    length_d_srch = 4 + 2 * complexity;
+    celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+    silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
+
+    /* Escape if correlation is very low already here */
+    Cmax = C[ 0 ][ min_lag_4kHz ];
+    if( Cmax < 0.2f ) {
+        silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) );
+        *LTPCorr      = 0.0f;
+        *lagIndex     = 0;
+        *contourIndex = 0;
+        return 1;
+    }
+
+    threshold = search_thres1 * Cmax;
+    for( i = 0; i < length_d_srch; i++ ) {
+        /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */
+        if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) {
+            d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 );
+        } else {
+            length_d_srch = i;
+            break;
+        }
+    }
+    celt_assert( length_d_srch > 0 );
+
+    for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
+        d_comp[ i ] = 0;
+    }
+    for( i = 0; i < length_d_srch; i++ ) {
+        d_comp[ d_srch[ i ] ] = 1;
+    }
+
+    /* Convolution */
+    for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
+        d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ];
+    }
+
+    length_d_srch = 0;
+    for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) {
+        if( d_comp[ i + 1 ] > 0 ) {
+            d_srch[ length_d_srch ] = i;
+            length_d_srch++;
+        }
+    }
+
+    /* Convolution */
+    for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
+        d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ];
+    }
+
+    length_d_comp = 0;
+    for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) {
+        if( d_comp[ i ] > 0 ) {
+            d_comp[ length_d_comp ] = (opus_int16)( i - 2 );
+            length_d_comp++;
+        }
+    }
+
+    /**********************************************************************************
+    ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
+    *************************************************************************************/
+    /*********************************************************************************
+    * Find energy of each subframe projected onto its history, for a range of delays
+    *********************************************************************************/
+    silk_memset( C, 0, PE_MAX_NB_SUBFR*((PE_MAX_LAG >> 1) + 5) * sizeof(silk_float));
+
+    if( Fs_kHz == 8 ) {
+        target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * 8 ];
+    } else {
+        target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ];
+    }
+    for( k = 0; k < nb_subfr; k++ ) {
+        energy_tmp = silk_energy_FLP( target_ptr, sf_length_8kHz ) + 1.0;
+        for( j = 0; j < length_d_comp; j++ ) {
+            d = d_comp[ j ];
+            basis_ptr = target_ptr - d;
+            cross_corr = silk_inner_product_FLP( basis_ptr, target_ptr, sf_length_8kHz, arch );
+            if( cross_corr > 0.0f ) {
+                energy = silk_energy_FLP( basis_ptr, sf_length_8kHz );
+                C[ k ][ d ] = (silk_float)( 2 * cross_corr / ( energy + energy_tmp ) );
+            } else {
+                C[ k ][ d ] = 0.0f;
+            }
+        }
+        target_ptr += sf_length_8kHz;
+    }
+
+    /* search over lag range and lags codebook */
+    /* scale factor for lag codebook, as a function of center lag */
+
+    CCmax   = 0.0f; /* This value doesn't matter */
+    CCmax_b = -1000.0f;
+
+    CBimax = 0; /* To avoid returning undefined lag values */
+    lag = -1;   /* To check if lag with strong enough correlation has been found */
+
+    if( prevLag > 0 ) {
+        if( Fs_kHz == 12 ) {
+            prevLag = silk_LSHIFT( prevLag, 1 ) / 3;
+        } else if( Fs_kHz == 16 ) {
+            prevLag = silk_RSHIFT( prevLag, 1 );
+        }
+        prevLag_log2 = silk_log2( (silk_float)prevLag );
+    } else {
+        prevLag_log2 = 0;
+    }
+
+    /* Set up stage 2 codebook based on number of subframes */
+    if( nb_subfr == PE_MAX_NB_SUBFR ) {
+        cbk_size   = PE_NB_CBKS_STAGE2_EXT;
+        Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
+        if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) {
+            /* If input is 8 khz use a larger codebook here because it is last stage */
+            nb_cbk_search = PE_NB_CBKS_STAGE2_EXT;
+        } else {
+            nb_cbk_search = PE_NB_CBKS_STAGE2;
+        }
+    } else {
+        cbk_size       = PE_NB_CBKS_STAGE2_10MS;
+        Lag_CB_ptr     = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
+        nb_cbk_search  = PE_NB_CBKS_STAGE2_10MS;
+    }
+
+    for( k = 0; k < length_d_srch; k++ ) {
+        d = d_srch[ k ];
+        for( j = 0; j < nb_cbk_search; j++ ) {
+            CC[j] = 0.0f;
+            for( i = 0; i < nb_subfr; i++ ) {
+                /* Try all codebooks */
+                CC[ j ] += C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )];
+            }
+        }
+        /* Find best codebook */
+        CCmax_new  = -1000.0f;
+        CBimax_new = 0;
+        for( i = 0; i < nb_cbk_search; i++ ) {
+            if( CC[ i ] > CCmax_new ) {
+                CCmax_new = CC[ i ];
+                CBimax_new = i;
+            }
+        }
+
+        /* Bias towards shorter lags */
+        lag_log2 = silk_log2( (silk_float)d );
+        CCmax_new_b = CCmax_new - PE_SHORTLAG_BIAS * nb_subfr * lag_log2;
+
+        /* Bias towards previous lag */
+        if( prevLag > 0 ) {
+            delta_lag_log2_sqr = lag_log2 - prevLag_log2;
+            delta_lag_log2_sqr *= delta_lag_log2_sqr;
+            CCmax_new_b -= PE_PREVLAG_BIAS * nb_subfr * (*LTPCorr) * delta_lag_log2_sqr / ( delta_lag_log2_sqr + 0.5f );
+        }
+
+        if( CCmax_new_b > CCmax_b &&                /* Find maximum biased correlation                  */
+            CCmax_new > nb_subfr * search_thres2    /* Correlation needs to be high enough to be voiced */
+        ) {
+            CCmax_b = CCmax_new_b;
+            CCmax   = CCmax_new;
+            lag     = d;
+            CBimax  = CBimax_new;
+        }
+    }
+
+    if( lag == -1 ) {
+        /* No suitable candidate found */
+        silk_memset( pitch_out, 0, PE_MAX_NB_SUBFR * sizeof(opus_int) );
+        *LTPCorr      = 0.0f;
+        *lagIndex     = 0;
+        *contourIndex = 0;
+        return 1;
+    }
+
+    /* Output normalized correlation */
+    *LTPCorr = (silk_float)( CCmax / nb_subfr );
+    silk_assert( *LTPCorr >= 0.0f );
+
+    if( Fs_kHz > 8 ) {
+        /* Search in original signal */
+
+        /* Compensate for decimation */
+        silk_assert( lag == silk_SAT16( lag ) );
+        if( Fs_kHz == 12 ) {
+            lag = silk_RSHIFT_ROUND( silk_SMULBB( lag, 3 ), 1 );
+        } else { /* Fs_kHz == 16 */
+            lag = silk_LSHIFT( lag, 1 );
+        }
+
+        lag = silk_LIMIT_int( lag, min_lag, max_lag );
+        start_lag = silk_max_int( lag - 2, min_lag );
+        end_lag   = silk_min_int( lag + 2, max_lag );
+        lag_new   = lag;                                    /* to avoid undefined lag */
+        CBimax    = 0;                                      /* to avoid undefined lag */
+
+        CCmax = -1000.0f;
+
+        /* Calculate the correlations and energies needed in stage 3 */
+        silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
+        silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity );
+
+        lag_counter = 0;
+        silk_assert( lag == silk_SAT16( lag ) );
+        contour_bias = PE_FLATCONTOUR_BIAS / lag;
+
+        /* Set up cbk parameters according to complexity setting and frame length */
+        if( nb_subfr == PE_MAX_NB_SUBFR ) {
+            nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
+            cbk_size      = PE_NB_CBKS_STAGE3_MAX;
+            Lag_CB_ptr    = &silk_CB_lags_stage3[ 0 ][ 0 ];
+        } else {
+            nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+            cbk_size      = PE_NB_CBKS_STAGE3_10MS;
+            Lag_CB_ptr    = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+        }
+
+        target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
+        energy_tmp = silk_energy_FLP( target_ptr, nb_subfr * sf_length ) + 1.0;
+        for( d = start_lag; d <= end_lag; d++ ) {
+            for( j = 0; j < nb_cbk_search; j++ ) {
+                cross_corr = 0.0;
+                energy = energy_tmp;
+                for( k = 0; k < nb_subfr; k++ ) {
+                    cross_corr += cross_corr_st3[ k ][ j ][ lag_counter ];
+                    energy     +=   energies_st3[ k ][ j ][ lag_counter ];
+                }
+                if( cross_corr > 0.0 ) {
+                    CCmax_new = (silk_float)( 2 * cross_corr / energy );
+                    /* Reduce depending on flatness of contour */
+                    CCmax_new *= 1.0f - contour_bias * j;
+                } else {
+                    CCmax_new = 0.0f;
+                }
+
+                if( CCmax_new > CCmax && ( d + (opus_int)silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag ) {
+                    CCmax   = CCmax_new;
+                    lag_new = d;
+                    CBimax  = j;
+                }
+            }
+            lag_counter++;
+        }
+
+        for( k = 0; k < nb_subfr; k++ ) {
+            pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
+            pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag, PE_MAX_LAG_MS * Fs_kHz );
+        }
+        *lagIndex = (opus_int16)( lag_new - min_lag );
+        *contourIndex = (opus_int8)CBimax;
+    } else {        /* Fs_kHz == 8 */
+        /* Save Lags */
+        for( k = 0; k < nb_subfr; k++ ) {
+            pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
+            pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag_8kHz, PE_MAX_LAG_MS * 8 );
+        }
+        *lagIndex = (opus_int16)( lag - min_lag_8kHz );
+        *contourIndex = (opus_int8)CBimax;
+    }
+    celt_assert( *lagIndex >= 0 );
+    /* return as voiced */
+    return 0;
+}
+
+/***********************************************************************
+ * Calculates the correlations used in stage 3 search. In order to cover
+ * the whole lag codebook for all the searched offset lags (lag +- 2),
+ * the following correlations are needed in each sub frame:
+ *
+ * sf1: lag range [-8,...,7] total 16 correlations
+ * sf2: lag range [-4,...,4] total 9 correlations
+ * sf3: lag range [-3,....4] total 8 correltions
+ * sf4: lag range [-6,....8] total 15 correlations
+ *
+ * In total 48 correlations. The direct implementation computed in worst
+ * case 4*12*5 = 240 correlations, but more likely around 120.
+ ***********************************************************************/
+static void silk_P_Ana_calc_corr_st3(
+    silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+    const silk_float    frame[],            /* I vector to correlate                                            */
+    opus_int            start_lag,          /* I start lag                                                      */
+    opus_int            sf_length,          /* I sub frame length                                               */
+    opus_int            nb_subfr,           /* I number of subframes                                            */
+    opus_int            complexity,         /* I Complexity setting                                             */
+    int                 arch                /* I Run-time architecture                                          */
+)
+{
+    const silk_float *target_ptr;
+    opus_int   i, j, k, lag_counter, lag_low, lag_high;
+    opus_int   nb_cbk_search, delta, idx, cbk_size;
+    silk_float scratch_mem[ SCRATCH_SIZE ];
+    opus_val32 xcorr[ SCRATCH_SIZE ];
+    const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
+
+    celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+    celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+    if( nb_subfr == PE_MAX_NB_SUBFR ) {
+        Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
+        Lag_CB_ptr    = &silk_CB_lags_stage3[ 0 ][ 0 ];
+        nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
+        cbk_size      = PE_NB_CBKS_STAGE3_MAX;
+    } else {
+        celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+        Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
+        Lag_CB_ptr    = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+        nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+        cbk_size      = PE_NB_CBKS_STAGE3_10MS;
+    }
+
+    target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */
+    for( k = 0; k < nb_subfr; k++ ) {
+        lag_counter = 0;
+
+        /* Calculate the correlations for each subframe */
+        lag_low  = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+        lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
+        silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
+        celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr, sf_length, lag_high - lag_low + 1, arch );
+        for( j = lag_low; j <= lag_high; j++ ) {
+            silk_assert( lag_counter < SCRATCH_SIZE );
+            scratch_mem[ lag_counter ] = xcorr[ lag_high - j ];
+            lag_counter++;
+        }
+
+        delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+        for( i = 0; i < nb_cbk_search; i++ ) {
+            /* Fill out the 3 dim array that stores the correlations for */
+            /* each code_book vector for each start lag */
+            idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
+            for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
+                silk_assert( idx + j < SCRATCH_SIZE );
+                silk_assert( idx + j < lag_counter );
+                cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
+            }
+        }
+        target_ptr += sf_length;
+    }
+}
+
+/********************************************************************/
+/* Calculate the energies for first two subframes. The energies are */
+/* calculated recursively.                                          */
+/********************************************************************/
+static void silk_P_Ana_calc_energy_st3(
+    silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+    const silk_float    frame[],            /* I vector to correlate                                            */
+    opus_int            start_lag,          /* I start lag                                                      */
+    opus_int            sf_length,          /* I sub frame length                                               */
+    opus_int            nb_subfr,           /* I number of subframes                                            */
+    opus_int            complexity          /* I Complexity setting                                             */
+)
+{
+    const silk_float *target_ptr, *basis_ptr;
+    double    energy;
+    opus_int   k, i, j, lag_counter;
+    opus_int   nb_cbk_search, delta, idx, cbk_size, lag_diff;
+    silk_float scratch_mem[ SCRATCH_SIZE ];
+    const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
+
+    celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+    celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+    if( nb_subfr == PE_MAX_NB_SUBFR ) {
+        Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
+        Lag_CB_ptr    = &silk_CB_lags_stage3[ 0 ][ 0 ];
+        nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
+        cbk_size      = PE_NB_CBKS_STAGE3_MAX;
+    } else {
+        celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+        Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
+        Lag_CB_ptr    = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+        nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+        cbk_size      = PE_NB_CBKS_STAGE3_10MS;
+    }
+
+    target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ];
+    for( k = 0; k < nb_subfr; k++ ) {
+        lag_counter = 0;
+
+        /* Calculate the energy for first lag */
+        basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) );
+        energy = silk_energy_FLP( basis_ptr, sf_length ) + 1e-3;
+        silk_assert( energy >= 0.0 );
+        scratch_mem[lag_counter] = (silk_float)energy;
+        lag_counter++;
+
+        lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) -  matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 );
+        for( i = 1; i < lag_diff; i++ ) {
+            /* remove part outside new window */
+            energy -= basis_ptr[sf_length - i] * (double)basis_ptr[sf_length - i];
+            silk_assert( energy >= 0.0 );
+
+            /* add part that comes into window */
+            energy += basis_ptr[ -i ] * (double)basis_ptr[ -i ];
+            silk_assert( energy >= 0.0 );
+            silk_assert( lag_counter < SCRATCH_SIZE );
+            scratch_mem[lag_counter] = (silk_float)energy;
+            lag_counter++;
+        }
+
+        delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+        for( i = 0; i < nb_cbk_search; i++ ) {
+            /* Fill out the 3 dim array that stores the correlations for    */
+            /* each code_book vector for each start lag                     */
+            idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
+            for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
+                silk_assert( idx + j < SCRATCH_SIZE );
+                silk_assert( idx + j < lag_counter );
+                energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
+                silk_assert( energies_st3[ k ][ i ][ j ] >= 0.0f );
+            }
+        }
+        target_ptr += sf_length;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/process_gains_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/process_gains_FLP.c
new file mode 100644 (file)
index 0000000..c0da0da
--- /dev/null
@@ -0,0 +1,103 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* Processing of gains */
+void silk_process_gains_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+)
+{
+    silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
+    opus_int     k;
+    opus_int32   pGains_Q16[ MAX_NB_SUBFR ];
+    silk_float   s, InvMaxSqrVal, gain, quant_offset;
+
+    /* Gain reduction when LTP coding gain is high */
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        s = 1.0f - 0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) );
+        for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+            psEncCtrl->Gains[ k ] *= s;
+        }
+    }
+
+    /* Limit the quantized signal */
+    InvMaxSqrVal = ( silk_float )( pow( 2.0f, 0.33f * ( 21.0f - psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) ) ) / psEnc->sCmn.subfr_length );
+
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        /* Soft limit on ratio residual energy and squared gains */
+        gain = psEncCtrl->Gains[ k ];
+        gain = ( silk_float )sqrt( gain * gain + psEncCtrl->ResNrg[ k ] * InvMaxSqrVal );
+        psEncCtrl->Gains[ k ] = silk_min_float( gain, 32767.0f );
+    }
+
+    /* Prepare gains for noise shaping quantization */
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        pGains_Q16[ k ] = (opus_int32)( psEncCtrl->Gains[ k ] * 65536.0f );
+    }
+
+    /* Save unquantized gains and gain Index */
+    silk_memcpy( psEncCtrl->GainsUnq_Q16, pGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
+    psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
+
+    /* Quantize gains */
+    silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
+            &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+    /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+        psEncCtrl->Gains[ k ] = pGains_Q16[ k ] / 65536.0f;
+    }
+
+    /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */
+    if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+        if( psEncCtrl->LTPredCodGain + psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ) > 1.0f ) {
+            psEnc->sCmn.indices.quantOffsetType = 0;
+        } else {
+            psEnc->sCmn.indices.quantOffsetType = 1;
+        }
+    }
+
+    /* Quantizer boundary adjustment */
+    quant_offset = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ] / 1024.0f;
+    psEncCtrl->Lambda = LAMBDA_OFFSET
+                      + LAMBDA_DELAYED_DECISIONS * psEnc->sCmn.nStatesDelayedDecision
+                      + LAMBDA_SPEECH_ACT        * psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f )
+                      + LAMBDA_INPUT_QUALITY     * psEncCtrl->input_quality
+                      + LAMBDA_CODING_QUALITY    * psEncCtrl->coding_quality
+                      + LAMBDA_QUANT_OFFSET      * quant_offset;
+
+    silk_assert( psEncCtrl->Lambda > 0.0f );
+    silk_assert( psEncCtrl->Lambda < 2.0f );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/regularize_correlations_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/regularize_correlations_FLP.c
new file mode 100644 (file)
index 0000000..df46126
--- /dev/null
@@ -0,0 +1,48 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Add noise to matrix diagonal */
+void silk_regularize_correlations_FLP(
+    silk_float                      *XX,                                /* I/O  Correlation matrices                        */
+    silk_float                      *xx,                                /* I/O  Correlation values                          */
+    const silk_float                noise,                              /* I    Noise energy to add                         */
+    const opus_int                  D                                   /* I    Dimension of XX                             */
+)
+{
+    opus_int i;
+
+    for( i = 0; i < D; i++ ) {
+        matrix_ptr( &XX[ 0 ], i, i, D ) += noise;
+    }
+    xx[ 0 ] += noise;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/residual_energy_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/residual_energy_FLP.c
new file mode 100644 (file)
index 0000000..1bd07b3
--- /dev/null
@@ -0,0 +1,117 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+#define MAX_ITERATIONS_RESIDUAL_NRG         10
+#define REGULARIZATION_FACTOR               1e-8f
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+silk_float silk_residual_energy_covar_FLP(                              /* O    Weighted residual energy                    */
+    const silk_float                *c,                                 /* I    Filter coefficients                         */
+    silk_float                      *wXX,                               /* I/O  Weighted correlation matrix, reg. out       */
+    const silk_float                *wXx,                               /* I    Weighted correlation vector                 */
+    const silk_float                wxx,                                /* I    Weighted correlation value                  */
+    const opus_int                  D                                   /* I    Dimension                                   */
+)
+{
+    opus_int   i, j, k;
+    silk_float tmp, nrg = 0.0f, regularization;
+
+    /* Safety checks */
+    celt_assert( D >= 0 );
+
+    regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] );
+    for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) {
+        nrg = wxx;
+
+        tmp = 0.0f;
+        for( i = 0; i < D; i++ ) {
+            tmp += wXx[ i ] * c[ i ];
+        }
+        nrg -= 2.0f * tmp;
+
+        /* compute c' * wXX * c, assuming wXX is symmetric */
+        for( i = 0; i < D; i++ ) {
+            tmp = 0.0f;
+            for( j = i + 1; j < D; j++ ) {
+                tmp += matrix_c_ptr( wXX, i, j, D ) * c[ j ];
+            }
+            nrg += c[ i ] * ( 2.0f * tmp + matrix_c_ptr( wXX, i, i, D ) * c[ i ] );
+        }
+        if( nrg > 0 ) {
+            break;
+        } else {
+            /* Add white noise */
+            for( i = 0; i < D; i++ ) {
+                matrix_c_ptr( wXX, i, i, D ) +=  regularization;
+            }
+            /* Increase noise for next run */
+            regularization *= 2.0f;
+        }
+    }
+    if( k == MAX_ITERATIONS_RESIDUAL_NRG ) {
+        silk_assert( nrg == 0 );
+        nrg = 1.0f;
+    }
+
+    return nrg;
+}
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order   */
+/* of preceding samples                                                                 */
+void silk_residual_energy_FLP(
+    silk_float                      nrgs[ MAX_NB_SUBFR ],               /* O    Residual energy per subframe                */
+    const silk_float                x[],                                /* I    Input signal                                */
+    silk_float                      a[ 2 ][ MAX_LPC_ORDER ],            /* I    AR coefs for each frame half                */
+    const silk_float                gains[],                            /* I    Quantization gains                          */
+    const opus_int                  subfr_length,                       /* I    Subframe length                             */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    const opus_int                  LPC_order                           /* I    LPC order                                   */
+)
+{
+    opus_int     shift;
+    silk_float   *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ];
+
+    LPC_res_ptr = LPC_res + LPC_order;
+    shift = LPC_order + subfr_length;
+
+    /* Filter input to create the LPC residual for each frame half, and measure subframe energies */
+    silk_LPC_analysis_filter_FLP( LPC_res, a[ 0 ], x + 0 * shift, 2 * shift, LPC_order );
+    nrgs[ 0 ] = ( silk_float )( gains[ 0 ] * gains[ 0 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) );
+    nrgs[ 1 ] = ( silk_float )( gains[ 1 ] * gains[ 1 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) );
+
+    if( nb_subfr == MAX_NB_SUBFR ) {
+        silk_LPC_analysis_filter_FLP( LPC_res, a[ 1 ], x + 2 * shift, 2 * shift, LPC_order );
+        nrgs[ 2 ] = ( silk_float )( gains[ 2 ] * gains[ 2 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) );
+        nrgs[ 3 ] = ( silk_float )( gains[ 3 ] * gains[ 3 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_copy_vector_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_copy_vector_FLP.c
new file mode 100644 (file)
index 0000000..20db32b
--- /dev/null
@@ -0,0 +1,57 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* copy and multiply a vector by a constant */
+void silk_scale_copy_vector_FLP(
+    silk_float          *data_out,
+    const silk_float    *data_in,
+    silk_float          gain,
+    opus_int            dataSize
+)
+{
+    opus_int  i, dataSize4;
+
+    /* 4x unrolled loop */
+    dataSize4 = dataSize & 0xFFFC;
+    for( i = 0; i < dataSize4; i += 4 ) {
+        data_out[ i + 0 ] = gain * data_in[ i + 0 ];
+        data_out[ i + 1 ] = gain * data_in[ i + 1 ];
+        data_out[ i + 2 ] = gain * data_in[ i + 2 ];
+        data_out[ i + 3 ] = gain * data_in[ i + 3 ];
+    }
+
+    /* any remaining elements */
+    for( ; i < dataSize; i++ ) {
+        data_out[ i ] = gain * data_in[ i ];
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_vector_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/scale_vector_FLP.c
new file mode 100644 (file)
index 0000000..108fdcb
--- /dev/null
@@ -0,0 +1,56 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* multiply a vector by a constant */
+void silk_scale_vector_FLP(
+    silk_float          *data1,
+    silk_float          gain,
+    opus_int            dataSize
+)
+{
+    opus_int  i, dataSize4;
+
+    /* 4x unrolled loop */
+    dataSize4 = dataSize & 0xFFFC;
+    for( i = 0; i < dataSize4; i += 4 ) {
+        data1[ i + 0 ] *= gain;
+        data1[ i + 1 ] *= gain;
+        data1[ i + 2 ] *= gain;
+        data1[ i + 3 ] *= gain;
+    }
+
+    /* any remaining elements */
+    for( ; i < dataSize; i++ ) {
+        data1[ i ] *= gain;
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/schur_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/schur_FLP.c
new file mode 100644 (file)
index 0000000..8526c74
--- /dev/null
@@ -0,0 +1,70 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+silk_float silk_schur_FLP(                  /* O    returns residual energy                                     */
+    silk_float          refl_coef[],        /* O    reflection coefficients (length order)                      */
+    const silk_float    auto_corr[],        /* I    autocorrelation sequence (length order+1)                   */
+    opus_int            order               /* I    order                                                       */
+)
+{
+    opus_int   k, n;
+    double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
+    double Ctmp1, Ctmp2, rc_tmp;
+
+    celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+
+    /* Copy correlations */
+    k = 0;
+    do {
+        C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
+    } while( ++k <= order );
+
+    for( k = 0; k < order; k++ ) {
+        /* Get reflection coefficient */
+        rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );
+
+        /* Save the output */
+        refl_coef[ k ] = (silk_float)rc_tmp;
+
+        /* Update correlations */
+        for( n = 0; n < order - k; n++ ) {
+            Ctmp1 = C[ n + k + 1 ][ 0 ];
+            Ctmp2 = C[ n ][ 1 ];
+            C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp;
+            C[ n ][ 1 ]         = Ctmp2 + Ctmp1 * rc_tmp;
+        }
+    }
+
+    /* Return residual energy */
+    return (silk_float)C[ 0 ][ 1 ];
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/sort_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/sort_FLP.c
new file mode 100644 (file)
index 0000000..0e18f31
--- /dev/null
@@ -0,0 +1,83 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Insertion sort (fast for already almost sorted arrays):  */
+/* Best case:  O(n)   for an already sorted array           */
+/* Worst case: O(n^2) for an inversely sorted array         */
+
+#include "typedef.h"
+#include "SigProc_FLP.h"
+
+void silk_insertion_sort_decreasing_FLP(
+    silk_float          *a,                 /* I/O  Unsorted / Sorted vector                                    */
+    opus_int            *idx,               /* O    Index vector for the sorted elements                        */
+    const opus_int      L,                  /* I    Vector length                                               */
+    const opus_int      K                   /* I    Number of correctly sorted positions                        */
+)
+{
+    silk_float value;
+    opus_int   i, j;
+
+    /* Safety checks */
+    celt_assert( K >  0 );
+    celt_assert( L >  0 );
+    celt_assert( L >= K );
+
+    /* Write start indices in index vector */
+    for( i = 0; i < K; i++ ) {
+        idx[ i ] = i;
+    }
+
+    /* Sort vector elements by value, decreasing order */
+    for( i = 1; i < K; i++ ) {
+        value = a[ i ];
+        for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+            a[ j + 1 ]   = a[ j ];      /* Shift value */
+            idx[ j + 1 ] = idx[ j ];    /* Shift index */
+        }
+        a[ j + 1 ]   = value;   /* Write value */
+        idx[ j + 1 ] = i;       /* Write index */
+    }
+
+    /* If less than L values are asked check the remaining values,      */
+    /* but only spend CPU to ensure that the K first values are correct */
+    for( i = K; i < L; i++ ) {
+        value = a[ i ];
+        if( value > a[ K - 1 ] ) {
+            for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+                a[ j + 1 ]   = a[ j ];      /* Shift value */
+                idx[ j + 1 ] = idx[ j ];    /* Shift index */
+            }
+            a[ j + 1 ]   = value;   /* Write value */
+            idx[ j + 1 ] = i;       /* Write index */
+        }
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/warped_autocorrelation_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/warped_autocorrelation_FLP.c
new file mode 100644 (file)
index 0000000..116dab9
--- /dev/null
@@ -0,0 +1,75 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FLP(
+    silk_float                      *corr,                              /* O    Result [order + 1]                          */
+    const silk_float                *input,                             /* I    Input data to correlate                     */
+    const silk_float                warping,                            /* I    Warping coefficient                         */
+    const opus_int                  length,                             /* I    Length of input                             */
+    const opus_int                  order                               /* I    Correlation order (even)                    */
+)
+{
+    opus_int    n, i;
+    double      tmp1, tmp2;
+    double      state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+    double      C[     MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+
+    /* Order must be even */
+    celt_assert( ( order & 1 ) == 0 );
+
+    /* Loop over samples */
+    for( n = 0; n < length; n++ ) {
+        tmp1 = input[ n ];
+        /* Loop over allpass sections */
+        for( i = 0; i < order; i += 2 ) {
+            /* Output of allpass section */
+            /* We voluntarily use two multiples instead of factoring the expression to
+               reduce the length of the dependency chain (tmp1->tmp2->tmp1... ). */
+            tmp2 = state[ i ] + warping * state[ i + 1 ] - warping * tmp1;
+            state[ i ] = tmp1;
+            C[ i ] += state[ 0 ] * tmp1;
+            /* Output of allpass section */
+            tmp1 = state[ i + 1 ] + warping * state[ i + 2 ] - warping * tmp2;
+            state[ i + 1 ] = tmp2;
+            C[ i + 1 ] += state[ 0 ] * tmp2;
+        }
+        state[ order ] = tmp1;
+        C[ order ] += state[ 0 ] * tmp1;
+    }
+
+    /* Copy correlations in silk_float output format */
+    for( i = 0; i < order + 1; i++ ) {
+        corr[ i ] = ( silk_float )C[ i ];
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/wrappers_FLP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/float/wrappers_FLP.c
new file mode 100644 (file)
index 0000000..c0c183e
--- /dev/null
@@ -0,0 +1,209 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Wrappers. Calls flp / fix code */
+
+/* Convert AR filter coefficients to NLSF parameters */
+void silk_A2NLSF_FLP(
+    opus_int16                      *NLSF_Q15,                          /* O    NLSF vector      [ LPC_order ]              */
+    const silk_float                *pAR,                               /* I    LPC coefficients [ LPC_order ]              */
+    const opus_int                  LPC_order                           /* I    LPC order                                   */
+)
+{
+    opus_int   i;
+    opus_int32 a_fix_Q16[ MAX_LPC_ORDER ];
+
+    for( i = 0; i < LPC_order; i++ ) {
+        a_fix_Q16[ i ] = silk_float2int( pAR[ i ] * 65536.0f );
+    }
+
+    silk_A2NLSF( NLSF_Q15, a_fix_Q16, LPC_order );
+}
+
+/* Convert LSF parameters to AR prediction filter coefficients */
+void silk_NLSF2A_FLP(
+    silk_float                      *pAR,                               /* O    LPC coefficients [ LPC_order ]              */
+    const opus_int16                *NLSF_Q15,                          /* I    NLSF vector      [ LPC_order ]              */
+    const opus_int                  LPC_order,                          /* I    LPC order                                   */
+    int                             arch                                /* I    Run-time architecture                       */
+)
+{
+    opus_int   i;
+    opus_int16 a_fix_Q12[ MAX_LPC_ORDER ];
+
+    silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order, arch );
+
+    for( i = 0; i < LPC_order; i++ ) {
+        pAR[ i ] = ( silk_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f );
+    }
+}
+
+/******************************************/
+/* Floating-point NLSF processing wrapper */
+/******************************************/
+void silk_process_NLSFs_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
+    silk_float                      PredCoef[ 2 ][ MAX_LPC_ORDER ],     /* O    Prediction coefficients                     */
+    opus_int16                      NLSF_Q15[      MAX_LPC_ORDER ],     /* I/O  Normalized LSFs (quant out) (0 - (2^15-1))  */
+    const opus_int16                prev_NLSF_Q15[ MAX_LPC_ORDER ]      /* I    Previous Normalized LSFs (0 - (2^15-1))     */
+)
+{
+    opus_int     i, j;
+    opus_int16   PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+
+    silk_process_NLSFs( psEncC, PredCoef_Q12, NLSF_Q15, prev_NLSF_Q15);
+
+    for( j = 0; j < 2; j++ ) {
+        for( i = 0; i < psEncC->predictLPCOrder; i++ ) {
+            PredCoef[ j ][ i ] = ( silk_float )PredCoef_Q12[ j ][ i ] * ( 1.0f / 4096.0f );
+        }
+    }
+}
+
+/****************************************/
+/* Floating-point Silk NSQ wrapper      */
+/****************************************/
+void silk_NSQ_wrapper_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    SideInfoIndices                 *psIndices,                         /* I/O  Quantization indices                        */
+    silk_nsq_state                  *psNSQ,                             /* I/O  Noise Shaping Quantzation state             */
+    opus_int8                       pulses[],                           /* O    Quantized pulse signal                      */
+    const silk_float                x[]                                 /* I    Prefiltered input signal                    */
+)
+{
+    opus_int     i, j;
+    opus_int16   x16[ MAX_FRAME_LENGTH ];
+    opus_int32   Gains_Q16[ MAX_NB_SUBFR ];
+    silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+    opus_int16   LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+    opus_int     LTP_scale_Q14;
+
+    /* Noise shaping parameters */
+    opus_int16   AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    opus_int32   LF_shp_Q14[ MAX_NB_SUBFR ];         /* Packs two int16 coefficients per int32 value             */
+    opus_int     Lambda_Q10;
+    opus_int     Tilt_Q14[ MAX_NB_SUBFR ];
+    opus_int     HarmShapeGain_Q14[ MAX_NB_SUBFR ];
+
+    /* Convert control struct to fix control struct */
+    /* Noise shape parameters */
+    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+        for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) {
+            AR_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
+        }
+    }
+
+    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+        LF_shp_Q14[ i ] =   silk_LSHIFT32( silk_float2int( psEncCtrl->LF_AR_shp[ i ]     * 16384.0f ), 16 ) |
+                              (opus_uint16)silk_float2int( psEncCtrl->LF_MA_shp[ i ]     * 16384.0f );
+        Tilt_Q14[ i ]   =        (opus_int)silk_float2int( psEncCtrl->Tilt[ i ]          * 16384.0f );
+        HarmShapeGain_Q14[ i ] = (opus_int)silk_float2int( psEncCtrl->HarmShapeGain[ i ] * 16384.0f );
+    }
+    Lambda_Q10 = ( opus_int )silk_float2int( psEncCtrl->Lambda * 1024.0f );
+
+    /* prediction and coding parameters */
+    for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) {
+        LTPCoef_Q14[ i ] = (opus_int16)silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f );
+    }
+
+    for( j = 0; j < 2; j++ ) {
+        for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) {
+            PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f );
+        }
+    }
+
+    for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+        Gains_Q16[ i ] = silk_float2int( psEncCtrl->Gains[ i ] * 65536.0f );
+        silk_assert( Gains_Q16[ i ] > 0 );
+    }
+
+    if( psIndices->signalType == TYPE_VOICED ) {
+        LTP_scale_Q14 = silk_LTPScales_table_Q14[ psIndices->LTP_scaleIndex ];
+    } else {
+        LTP_scale_Q14 = 0;
+    }
+
+    /* Convert input to fix */
+    for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+        x16[ i ] = silk_float2int( x[ i ] );
+    }
+
+    /* Call NSQ */
+    if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
+        silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+            AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+    } else {
+        silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+            AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+    }
+}
+
+/***********************************************/
+/* Floating-point Silk LTP quantiation wrapper */
+/***********************************************/
+void silk_quant_LTP_gains_FLP(
+    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    Quantized LTP gains                            */
+    opus_int8                       cbk_index[ MAX_NB_SUBFR ],          /* O    Codebook index                              */
+    opus_int8                       *periodicity_index,                 /* O    Periodicity index                           */
+    opus_int32                      *sum_log_gain_Q7,                   /* I/O  Cumulative max prediction gain  */
+    silk_float                      *pred_gain_dB,                        /* O    LTP prediction gain                            */
+    const silk_float                XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Correlation matrix                    */
+    const silk_float                xX[ MAX_NB_SUBFR * LTP_ORDER ],        /* I    Correlation vector                            */
+    const opus_int                    subfr_len,                            /* I    Number of samples per subframe                */
+    const opus_int                    nb_subfr,                           /* I    Number of subframes                            */
+    int                             arch                                /* I    Run-time architecture                       */
+)
+{
+    opus_int   i, pred_gain_dB_Q7;
+    opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ];
+    opus_int32 XX_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+    opus_int32 xX_Q17[ MAX_NB_SUBFR * LTP_ORDER ];
+
+    i = 0;
+    do {
+        XX_Q17[ i ] = (opus_int32)silk_float2int( XX[ i ] * 131072.0f );
+    } while ( ++i < nb_subfr * LTP_ORDER * LTP_ORDER );
+    i = 0;
+    do {
+        xX_Q17[ i ] = (opus_int32)silk_float2int( xX[ i ] * 131072.0f );
+    } while ( ++i < nb_subfr * LTP_ORDER );
+
+    silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, &pred_gain_dB_Q7, XX_Q17, xX_Q17, subfr_len, nb_subfr, arch );
+
+    for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
+        B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
+    }
+
+    *pred_gain_dB = (silk_float)pred_gain_dB_Q7 * ( 1.0f / 128.0f );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/gain_quant.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/gain_quant.c
new file mode 100644 (file)
index 0000000..ee65245
--- /dev/null
@@ -0,0 +1,142 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+#define OFFSET                  ( ( MIN_QGAIN_DB * 128 ) / 6 + 16 * 128 )
+#define SCALE_Q16               ( ( 65536 * ( N_LEVELS_QGAIN - 1 ) ) / ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) )
+#define INV_SCALE_Q16           ( ( 65536 * ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) / ( N_LEVELS_QGAIN - 1 ) )
+
+/* Gain scalar quantization with hysteresis, uniform on log scale */
+void silk_gains_quant(
+    opus_int8                   ind[ MAX_NB_SUBFR ],            /* O    gain indices                                */
+    opus_int32                  gain_Q16[ MAX_NB_SUBFR ],       /* I/O  gains (quantized out)                       */
+    opus_int8                   *prev_ind,                      /* I/O  last index in previous frame                */
+    const opus_int              conditional,                    /* I    first gain is delta coded if 1              */
+    const opus_int              nb_subfr                        /* I    number of subframes                         */
+)
+{
+    opus_int k, double_step_size_threshold;
+
+    for( k = 0; k < nb_subfr; k++ ) {
+        /* Convert to log scale, scale, floor() */
+        ind[ k ] = silk_SMULWB( SCALE_Q16, silk_lin2log( gain_Q16[ k ] ) - OFFSET );
+
+        /* Round towards previous quantized gain (hysteresis) */
+        if( ind[ k ] < *prev_ind ) {
+            ind[ k ]++;
+        }
+        ind[ k ] = silk_LIMIT_int( ind[ k ], 0, N_LEVELS_QGAIN - 1 );
+
+        /* Compute delta indices and limit */
+        if( k == 0 && conditional == 0 ) {
+            /* Full index */
+            ind[ k ] = silk_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 );
+            *prev_ind = ind[ k ];
+        } else {
+            /* Delta index */
+            ind[ k ] = ind[ k ] - *prev_ind;
+
+            /* Double the quantization step size for large gain increases, so that the max gain level can be reached */
+            double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
+            if( ind[ k ] > double_step_size_threshold ) {
+                ind[ k ] = double_step_size_threshold + silk_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 );
+            }
+
+            ind[ k ] = silk_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT );
+
+            /* Accumulate deltas */
+            if( ind[ k ] > double_step_size_threshold ) {
+                *prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
+                *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
+            } else {
+                *prev_ind += ind[ k ];
+            }
+
+            /* Shift to make non-negative */
+            ind[ k ] -= MIN_DELTA_GAIN_QUANT;
+        }
+
+        /* Scale and convert to linear scale */
+        gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */
+    }
+}
+
+/* Gains scalar dequantization, uniform on log scale */
+void silk_gains_dequant(
+    opus_int32                  gain_Q16[ MAX_NB_SUBFR ],       /* O    quantized gains                             */
+    const opus_int8             ind[ MAX_NB_SUBFR ],            /* I    gain indices                                */
+    opus_int8                   *prev_ind,                      /* I/O  last index in previous frame                */
+    const opus_int              conditional,                    /* I    first gain is delta coded if 1              */
+    const opus_int              nb_subfr                        /* I    number of subframes                          */
+)
+{
+    opus_int   k, ind_tmp, double_step_size_threshold;
+
+    for( k = 0; k < nb_subfr; k++ ) {
+        if( k == 0 && conditional == 0 ) {
+            /* Gain index is not allowed to go down more than 16 steps (~21.8 dB) */
+            *prev_ind = silk_max_int( ind[ k ], *prev_ind - 16 );
+        } else {
+            /* Delta index */
+            ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT;
+
+            /* Accumulate deltas */
+            double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
+            if( ind_tmp > double_step_size_threshold ) {
+                *prev_ind += silk_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold;
+            } else {
+                *prev_ind += ind_tmp;
+            }
+        }
+        *prev_ind = silk_LIMIT_int( *prev_ind, 0, N_LEVELS_QGAIN - 1 );
+
+        /* Scale and convert to linear scale */
+        gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */
+    }
+}
+
+/* Compute unique identifier of gain indices vector */
+opus_int32 silk_gains_ID(                                       /* O    returns unique identifier of gains          */
+    const opus_int8             ind[ MAX_NB_SUBFR ],            /* I    gain indices                                */
+    const opus_int              nb_subfr                        /* I    number of subframes                         */
+)
+{
+    opus_int   k;
+    opus_int32 gainsID;
+
+    gainsID = 0;
+    for( k = 0; k < nb_subfr; k++ ) {
+        gainsID = silk_ADD_LSHIFT32( ind[ k ], gainsID, 8 );
+    }
+
+    return gainsID;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/init_decoder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/init_decoder.c
new file mode 100644 (file)
index 0000000..64fbd7e
--- /dev/null
@@ -0,0 +1,83 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+#include "structs.h"
+
+/************************/
+/* Reset Decoder State  */
+/************************/
+opus_int silk_reset_decoder(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state pointer                       */
+)
+{
+    /* Clear the entire encoder state, except anything copied */
+    silk_memset( &psDec->SILK_DECODER_STATE_RESET_START, 0, sizeof( silk_decoder_state ) - ((char*) &psDec->SILK_DECODER_STATE_RESET_START - (char*)psDec) );
+
+    /* Used to deactivate LSF interpolation */
+    psDec->first_frame_after_reset = 1;
+    psDec->prev_gain_Q16 = 65536;
+    psDec->arch = opus_select_arch();
+
+    /* Reset CNG state */
+    silk_CNG_Reset( psDec );
+
+    /* Reset PLC state */
+    silk_PLC_Reset( psDec );
+
+#ifdef ENABLE_OSCE
+    /* Reset OSCE state and method */
+    osce_reset(&psDec->osce, OSCE_DEFAULT_METHOD);
+#endif
+
+    return 0;
+}
+
+
+/************************/
+/* Init Decoder State   */
+/************************/
+opus_int silk_init_decoder(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state pointer                       */
+)
+{
+    /* Clear the entire encoder state, except anything copied */
+    silk_memset( psDec, 0, sizeof( silk_decoder_state ) );
+
+    silk_reset_decoder( psDec );
+
+    return(0);
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/inner_prod_aligned.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/inner_prod_aligned.c
new file mode 100644 (file)
index 0000000..257ae9e
--- /dev/null
@@ -0,0 +1,47 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+opus_int32 silk_inner_prod_aligned_scale(
+    const opus_int16 *const     inVec1,             /*    I input vector 1                                              */
+    const opus_int16 *const     inVec2,             /*    I input vector 2                                              */
+    const opus_int              scale,              /*    I number of bits to shift                                     */
+    const opus_int              len                 /*    I vector lengths                                              */
+)
+{
+    opus_int   i;
+    opus_int32 sum = 0;
+    for( i = 0; i < len; i++ ) {
+        sum = silk_ADD_RSHIFT32( sum, silk_SMULBB( inVec1[ i ], inVec2[ i ] ), scale );
+    }
+    return sum;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/interpolate.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/interpolate.c
new file mode 100644 (file)
index 0000000..833c28e
--- /dev/null
@@ -0,0 +1,51 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Interpolate two vectors */
+void silk_interpolate(
+    opus_int16                  xi[ MAX_LPC_ORDER ],            /* O    interpolated vector                         */
+    const opus_int16            x0[ MAX_LPC_ORDER ],            /* I    first vector                                */
+    const opus_int16            x1[ MAX_LPC_ORDER ],            /* I    second vector                               */
+    const opus_int              ifact_Q2,                       /* I    interp. factor, weight on 2nd vector        */
+    const opus_int              d                               /* I    number of parameters                        */
+)
+{
+    opus_int i;
+
+    celt_assert( ifact_Q2 >= 0 );
+    celt_assert( ifact_Q2 <= 4 );
+
+    for( i = 0; i < d; i++ ) {
+        xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/lin2log.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/lin2log.c
new file mode 100644 (file)
index 0000000..5a05d82
--- /dev/null
@@ -0,0 +1,45 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+/* Approximation of 128 * log2() (very close inverse of silk_log2lin()) */
+/* Convert input to a log scale    */
+opus_int32 silk_lin2log(
+    const opus_int32            inLin               /* I  input in linear scale                                         */
+)
+{
+    opus_int32 lz, frac_Q7;
+
+    silk_CLZ_FRAC( inLin, &lz, &frac_Q7 );
+
+    /* Piece-wise parabolic approximation */
+    return silk_ADD_LSHIFT32( silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ), 31 - lz, 7 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/log2lin.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/log2lin.c
new file mode 100644 (file)
index 0000000..b7c48e4
--- /dev/null
@@ -0,0 +1,58 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Approximation of 2^() (very close inverse of silk_lin2log()) */
+/* Convert input to a linear scale    */
+opus_int32 silk_log2lin(
+    const opus_int32            inLog_Q7            /* I  input on log scale                                            */
+)
+{
+    opus_int32 out, frac_Q7;
+
+    if( inLog_Q7 < 0 ) {
+        return 0;
+    } else if ( inLog_Q7 >= 3967 ) {
+        return silk_int32_MAX;
+    }
+
+    out = silk_LSHIFT( 1, silk_RSHIFT( inLog_Q7, 7 ) );
+    frac_Q7 = inLog_Q7 & 0x7F;
+    if( inLog_Q7 < 2048 ) {
+        /* Piece-wise parabolic approximation */
+        out = silk_ADD_RSHIFT32( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 );
+    } else {
+        /* Piece-wise parabolic approximation */
+        out = silk_MLA( out, silk_RSHIFT( out, 7 ), silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) );
+    }
+    return out;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros.h
new file mode 100644 (file)
index 0000000..26cfeb6
--- /dev/null
@@ -0,0 +1,154 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MACROS_H
+#define SILK_MACROS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "arch.h"
+
+/* This is an OPUS_INLINE header file for general platform. */
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#if OPUS_FAST_INT64
+#define silk_SMULWB(a32, b32)            ((opus_int32)(((a32) * (opus_int64)((opus_int16)(b32))) >> 16))
+#else
+#define silk_SMULWB(a32, b32)            ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16))
+#endif
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#if OPUS_FAST_INT64
+#define silk_SMLAWB(a32, b32, c32)       ((opus_int32)((a32) + (((b32) * (opus_int64)((opus_int16)(c32))) >> 16)))
+#else
+#define silk_SMLAWB(a32, b32, c32)       ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)))
+#endif
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMULWT(a32, b32)            ((opus_int32)(((a32) * (opus_int64)((b32) >> 16)) >> 16))
+#else
+#define silk_SMULWT(a32, b32)            (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16))
+#endif
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMLAWT(a32, b32, c32)       ((opus_int32)((a32) + (((b32) * ((opus_int64)(c32) >> 16)) >> 16)))
+#else
+#define silk_SMLAWT(a32, b32, c32)       ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16))
+#endif
+
+/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */
+#define silk_SMULBB(a32, b32)            ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32)))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */
+#define silk_SMLABB(a32, b32, c32)       ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
+
+/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */
+#define silk_SMULBT(a32, b32)            ((opus_int32)((opus_int16)(a32)) * ((b32) >> 16))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */
+#define silk_SMLABT(a32, b32, c32)       ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16))
+
+/* a64 + (b32 * c32) */
+#define silk_SMLAL(a64, b32, c32)        (silk_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32))))
+
+/* (a32 * b32) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMULWW(a32, b32)            ((opus_int32)(((opus_int64)(a32) * (b32)) >> 16))
+#else
+#define silk_SMULWW(a32, b32)            silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16))
+#endif
+
+/* a32 + ((b32 * c32) >> 16) */
+#if OPUS_FAST_INT64
+#define silk_SMLAWW(a32, b32, c32)       ((opus_int32)((a32) + (((opus_int64)(b32) * (c32)) >> 16)))
+#else
+#define silk_SMLAWW(a32, b32, c32)       silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16))
+#endif
+
+/* add/subtract with output saturated */
+#define silk_ADD_SAT32(a, b)             ((((opus_uint32)(a) + (opus_uint32)(b)) & 0x80000000) == 0 ?                              \
+                                        ((((a) & (b)) & 0x80000000) != 0 ? silk_int32_MIN : (a)+(b)) :   \
+                                        ((((a) | (b)) & 0x80000000) == 0 ? silk_int32_MAX : (a)+(b)) )
+
+#define silk_SUB_SAT32(a, b)             ((((opus_uint32)(a)-(opus_uint32)(b)) & 0x80000000) == 0 ?                                        \
+                                        (( (a) & ((b)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a)-(b)) :    \
+                                        ((((a)^0x80000000) & (b)  & 0x80000000) ? silk_int32_MAX : (a)-(b)) )
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/macros_mipsr1.h"
+#endif
+
+#include "ecintrin.h"
+#ifndef OVERRIDE_silk_CLZ16
+static OPUS_INLINE opus_int32 silk_CLZ16(opus_int16 in16)
+{
+    return 32 - EC_ILOG(in16<<16|0x8000);
+}
+#endif
+
+#ifndef OVERRIDE_silk_CLZ32
+static OPUS_INLINE opus_int32 silk_CLZ32(opus_int32 in32)
+{
+    return in32 ? 32 - EC_ILOG(in32) : 32;
+}
+#endif
+
+/* Row based */
+#define matrix_ptr(Matrix_base_adr, row, column, N) \
+    (*((Matrix_base_adr) + ((row)*(N)+(column))))
+#define matrix_adr(Matrix_base_adr, row, column, N) \
+      ((Matrix_base_adr) + ((row)*(N)+(column)))
+
+/* Column based */
+#ifndef matrix_c_ptr
+#   define matrix_c_ptr(Matrix_base_adr, row, column, M) \
+    (*((Matrix_base_adr) + ((row)+(M)*(column))))
+#endif
+
+#ifdef OPUS_ARM_INLINE_ASM
+#include "arm/macros_armv4.h"
+#endif
+
+#ifdef OPUS_ARM_INLINE_EDSP
+#include "arm/macros_armv5e.h"
+#endif
+
+#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
+#include "arm/macros_arm64.h"
+#endif
+
+#ifdef OPUS_XTENSA_LX7
+#include "xtensa/macros_lx7.h"
+#endif
+
+#endif /* SILK_MACROS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_arm64.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_arm64.h
new file mode 100644 (file)
index 0000000..ed03041
--- /dev/null
@@ -0,0 +1,39 @@
+/***********************************************************************
+Copyright (C) 2015 Vidyo
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MACROS_ARM64_H
+#define SILK_MACROS_ARM64_H
+
+#include <arm_neon.h>
+
+#undef silk_ADD_SAT32
+#define silk_ADD_SAT32(a, b) (vqadds_s32((a), (b)))
+
+#undef silk_SUB_SAT32
+#define silk_SUB_SAT32(a, b) (vqsubs_s32((a), (b)))
+
+#endif /* SILK_MACROS_ARM64_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv4.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv4.h
new file mode 100644 (file)
index 0000000..877eb18
--- /dev/null
@@ -0,0 +1,110 @@
+/***********************************************************************
+Copyright (C) 2013 Xiph.Org Foundation and contributors.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MACROS_ARMv4_H
+#define SILK_MACROS_ARMv4_H
+
+/* This macro only avoids the undefined behaviour from a left shift of
+   a negative value. It should only be used in macros that can't include
+   SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
+{
+  unsigned rd_lo;
+  int rd_hi;
+  __asm__(
+      "#silk_SMULWB\n\t"
+      "smull %0, %1, %2, %3\n\t"
+      : "=&r"(rd_lo), "=&r"(rd_hi)
+      : "%r"(a), "r"(SAFE_SHL(b,16))
+  );
+  return rd_hi;
+}
+#define silk_SMULWB(a, b) (silk_SMULWB_armv4(a, b))
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+#define silk_SMLAWB(a, b, c) ((a) + silk_SMULWB(b, c))
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT_armv4(opus_int32 a, opus_int32 b)
+{
+  unsigned rd_lo;
+  int rd_hi;
+  __asm__(
+      "#silk_SMULWT\n\t"
+      "smull %0, %1, %2, %3\n\t"
+      : "=&r"(rd_lo), "=&r"(rd_hi)
+      : "%r"(a), "r"(b&~0xFFFF)
+  );
+  return rd_hi;
+}
+#define silk_SMULWT(a, b) (silk_SMULWT_armv4(a, b))
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#undef silk_SMLAWT
+#define silk_SMLAWT(a, b, c) ((a) + silk_SMULWT(b, c))
+
+/* (a32 * b32) >> 16 */
+#undef silk_SMULWW
+static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b)
+{
+  unsigned rd_lo;
+  int rd_hi;
+  __asm__(
+    "#silk_SMULWW\n\t"
+    "smull %0, %1, %2, %3\n\t"
+    : "=&r"(rd_lo), "=&r"(rd_hi)
+    : "%r"(a), "r"(b)
+  );
+  return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+}
+#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
+
+#undef silk_SMLAWW
+static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  unsigned rd_lo;
+  int rd_hi;
+  __asm__(
+    "#silk_SMLAWW\n\t"
+    "smull %0, %1, %2, %3\n\t"
+    : "=&r"(rd_lo), "=&r"(rd_hi)
+    : "%r"(b), "r"(c)
+  );
+  return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+}
+#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
+
+#undef SAFE_SHL
+
+#endif /* SILK_MACROS_ARMv4_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv5e.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_armv5e.h
new file mode 100644 (file)
index 0000000..b14ec65
--- /dev/null
@@ -0,0 +1,220 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (c) 2013       Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MACROS_ARMv5E_H
+#define SILK_MACROS_ARMv5E_H
+
+/* This macro only avoids the undefined behaviour from a left shift of
+   a negative value. It should only be used in macros that can't include
+   SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
+{
+  int res;
+  __asm__(
+      "#silk_SMULWB\n\t"
+      "smulwb %0, %1, %2\n\t"
+      : "=r"(res)
+      : "r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SMULWB(a, b) (silk_SMULWB_armv5e(a, b))
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+static OPUS_INLINE opus_int32 silk_SMLAWB_armv5e(opus_int32 a, opus_int32 b,
+ opus_int16 c)
+{
+  int res;
+  __asm__(
+      "#silk_SMLAWB\n\t"
+      "smlawb %0, %1, %2, %3\n\t"
+      : "=r"(res)
+      : "r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_SMLAWB(a, b, c) (silk_SMLAWB_armv5e(a, b, c))
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT_armv5e(opus_int32 a, opus_int32 b)
+{
+  int res;
+  __asm__(
+      "#silk_SMULWT\n\t"
+      "smulwt %0, %1, %2\n\t"
+      : "=r"(res)
+      : "r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SMULWT(a, b) (silk_SMULWT_armv5e(a, b))
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#undef silk_SMLAWT
+static OPUS_INLINE opus_int32 silk_SMLAWT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  int res;
+  __asm__(
+      "#silk_SMLAWT\n\t"
+      "smlawt %0, %1, %2, %3\n\t"
+      : "=r"(res)
+      : "r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_SMLAWT(a, b, c) (silk_SMLAWT_armv5e(a, b, c))
+
+/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */
+#undef silk_SMULBB
+static OPUS_INLINE opus_int32 silk_SMULBB_armv5e(opus_int32 a, opus_int32 b)
+{
+  int res;
+  __asm__(
+      "#silk_SMULBB\n\t"
+      "smulbb %0, %1, %2\n\t"
+      : "=r"(res)
+      : "%r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SMULBB(a, b) (silk_SMULBB_armv5e(a, b))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */
+#undef silk_SMLABB
+static OPUS_INLINE opus_int32 silk_SMLABB_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  int res;
+  __asm__(
+      "#silk_SMLABB\n\t"
+      "smlabb %0, %1, %2, %3\n\t"
+      : "=r"(res)
+      : "%r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_SMLABB(a, b, c) (silk_SMLABB_armv5e(a, b, c))
+
+/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */
+#undef silk_SMULBT
+static OPUS_INLINE opus_int32 silk_SMULBT_armv5e(opus_int32 a, opus_int32 b)
+{
+  int res;
+  __asm__(
+      "#silk_SMULBT\n\t"
+      "smulbt %0, %1, %2\n\t"
+      : "=r"(res)
+      : "r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SMULBT(a, b) (silk_SMULBT_armv5e(a, b))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */
+#undef silk_SMLABT
+static OPUS_INLINE opus_int32 silk_SMLABT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+  int res;
+  __asm__(
+      "#silk_SMLABT\n\t"
+      "smlabt %0, %1, %2, %3\n\t"
+      : "=r"(res)
+      : "r"(b), "r"(c), "r"(a)
+  );
+  return res;
+}
+#define silk_SMLABT(a, b, c) (silk_SMLABT_armv5e(a, b, c))
+
+/* add/subtract with output saturated */
+#undef silk_ADD_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_SAT32_armv5e(opus_int32 a, opus_int32 b)
+{
+  int res;
+  __asm__(
+      "#silk_ADD_SAT32\n\t"
+      "qadd %0, %1, %2\n\t"
+      : "=r"(res)
+      : "%r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_ADD_SAT32(a, b) (silk_ADD_SAT32_armv5e(a, b))
+
+#undef silk_SUB_SAT32
+static OPUS_INLINE opus_int32 silk_SUB_SAT32_armv5e(opus_int32 a, opus_int32 b)
+{
+  int res;
+  __asm__(
+      "#silk_SUB_SAT32\n\t"
+      "qsub %0, %1, %2\n\t"
+      : "=r"(res)
+      : "r"(a), "r"(b)
+  );
+  return res;
+}
+#define silk_SUB_SAT32(a, b) (silk_SUB_SAT32_armv5e(a, b))
+
+#undef silk_CLZ16
+static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
+{
+  int res;
+  __asm__(
+      "#silk_CLZ16\n\t"
+      "clz %0, %1;\n"
+      : "=r"(res)
+      : "r"(SAFE_SHL(in16,16)|0x8000)
+  );
+  return res;
+}
+#define silk_CLZ16(in16) (silk_CLZ16_armv5(in16))
+
+#undef silk_CLZ32
+static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
+{
+  int res;
+  __asm__(
+      "#silk_CLZ32\n\t"
+      "clz %0, %1\n\t"
+      : "=r"(res)
+      : "r"(in32)
+  );
+  return res;
+}
+#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
+
+#undef SAFE_SHL
+
+#endif /* SILK_MACROS_ARMv5E_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_mipsr1.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/macros_mipsr1.h
new file mode 100644 (file)
index 0000000..7b12642
--- /dev/null
@@ -0,0 +1,123 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+
+#ifndef SILK_MACROS_MIPSR1_H__
+#define SILK_MACROS_MIPSR1_H__
+
+
+#if defined (__mips_dsp) && __mips == 32
+
+#undef silk_SMULWB
+static inline int silk_SMULWB(int a, int b)
+{
+    long long ac;
+    int c;
+
+    ac = __builtin_mips_mult(a, (opus_int32)(opus_int16)b);
+    c = __builtin_mips_extr_w(ac, 16);
+
+    return c;
+}
+
+#undef silk_SMLAWB
+#define silk_SMLAWB(a32, b32, c32)       ((a32) + silk_SMULWB(b32, c32))
+
+#undef silk_SMULWW
+static inline int silk_SMULWW(int a, int b)
+{
+    long long ac;
+    int c;
+
+    ac = __builtin_mips_mult(a, b);
+    c = __builtin_mips_extr_w(ac, 16);
+
+    return c;
+}
+
+#undef silk_SMLAWW
+static inline int silk_SMLAWW(int a, int b, int c)
+{
+    long long ac;
+    int res;
+
+    ac = __builtin_mips_mult(b, c);
+    res = __builtin_mips_extr_w(ac, 16);
+    res += a;
+
+    return res;
+}
+
+#elif defined (__mips_isa_rev) && __mips == 32
+
+#undef silk_SMULWB
+static inline int silk_SMULWB(int a, int b)
+{
+    long long ac = (long long)a * (int)(b << 16);
+
+    return ac >> 32;
+}
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+static inline int silk_SMLAWB(int a, int b, int c)
+{
+    long long ac = (long long)b * (int)(c << 16);
+
+    return a + (ac >> 32);
+}
+
+#endif
+
+#if defined (__mips_isa_rev) /* MIPS32r1+ */
+
+static inline int mips_clz(opus_uint32 x)
+{
+    return x ? __builtin_clz(x) : 32;
+}
+
+#define OVERRIDE_silk_CLZ16
+static inline opus_int32 silk_CLZ16(opus_int16 in16)
+{
+    int re32;
+    opus_uint32 in32 = (opus_uint16)in16;
+    re32 = mips_clz(in32);
+    re32 -= 16;
+    return re32;
+}
+
+#define OVERRIDE_silk_CLZ32
+static inline opus_int32 silk_CLZ32(opus_int32 in32)
+{
+    int re32;
+    re32 = mips_clz(in32);
+    return re32;
+}
+
+#endif /* __mips_isa_rev */
+
+#endif /* SILK_MACROS_MIPSR1_H__ */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main.h
new file mode 100644 (file)
index 0000000..5ca9aa5
--- /dev/null
@@ -0,0 +1,486 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MAIN_H
+#define SILK_MAIN_H
+
+#include "SigProc_FIX.h"
+#include "define.h"
+#include "structs.h"
+#include "tables.h"
+#include "PLC.h"
+#include "control.h"
+#include "debug.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/main_sse.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/NSQ_del_dec_arm.h"
+#endif
+
+/* Convert Left/Right stereo signal to adaptive Mid/Side representation */
+void silk_stereo_LR_to_MS(
+    stereo_enc_state            *state,                         /* I/O  State                                       */
+    opus_int16                  x1[],                           /* I/O  Left input signal, becomes mid signal       */
+    opus_int16                  x2[],                           /* I/O  Right input signal, becomes side signal     */
+    opus_int8                   ix[ 2 ][ 3 ],                   /* O    Quantization indices                        */
+    opus_int8                   *mid_only_flag,                 /* O    Flag: only mid signal coded                 */
+    opus_int32                  mid_side_rates_bps[],           /* O    Bitrates for mid and side signals           */
+    opus_int32                  total_rate_bps,                 /* I    Total bitrate                               */
+    opus_int                    prev_speech_act_Q8,             /* I    Speech activity level in previous frame     */
+    opus_int                    toMono,                         /* I    Last frame before a stereo->mono transition */
+    opus_int                    fs_kHz,                         /* I    Sample rate (kHz)                           */
+    opus_int                    frame_length                    /* I    Number of samples                           */
+);
+
+/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
+void silk_stereo_MS_to_LR(
+    stereo_dec_state            *state,                         /* I/O  State                                       */
+    opus_int16                  x1[],                           /* I/O  Left input signal, becomes mid signal       */
+    opus_int16                  x2[],                           /* I/O  Right input signal, becomes side signal     */
+    const opus_int32            pred_Q13[],                     /* I    Predictors                                  */
+    opus_int                    fs_kHz,                         /* I    Samples rate (kHz)                          */
+    opus_int                    frame_length                    /* I    Number of samples                           */
+);
+
+/* Find least-squares prediction gain for one signal based on another and quantize it */
+opus_int32 silk_stereo_find_predictor(                          /* O    Returns predictor in Q13                    */
+    opus_int32                  *ratio_Q14,                     /* O    Ratio of residual and mid energies          */
+    const opus_int16            x[],                            /* I    Basis signal                                */
+    const opus_int16            y[],                            /* I    Target signal                               */
+    opus_int32                  mid_res_amp_Q0[],               /* I/O  Smoothed mid, residual norms                */
+    opus_int                    length,                         /* I    Number of samples                           */
+    opus_int                    smooth_coef_Q16                 /* I    Smoothing coefficient                       */
+);
+
+/* Quantize mid/side predictors */
+void silk_stereo_quant_pred(
+    opus_int32                  pred_Q13[],                     /* I/O  Predictors (out: quantized)                 */
+    opus_int8                   ix[ 2 ][ 3 ]                    /* O    Quantization indices                        */
+);
+
+/* Entropy code the mid/side quantization indices */
+void silk_stereo_encode_pred(
+    ec_enc                      *psRangeEnc,                    /* I/O  Compressor data structure                   */
+    opus_int8                   ix[ 2 ][ 3 ]                    /* I    Quantization indices                        */
+);
+
+/* Entropy code the mid-only flag */
+void silk_stereo_encode_mid_only(
+    ec_enc                      *psRangeEnc,                    /* I/O  Compressor data structure                   */
+    opus_int8                   mid_only_flag
+);
+
+/* Decode mid/side predictors */
+void silk_stereo_decode_pred(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int32                  pred_Q13[]                      /* O    Predictors                                  */
+);
+
+/* Decode mid-only flag */
+void silk_stereo_decode_mid_only(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int                    *decode_only_mid                /* O    Flag that only mid channel has been coded   */
+);
+
+/* Encodes signs of excitation */
+void silk_encode_signs(
+    ec_enc                      *psRangeEnc,                        /* I/O  Compressor data structure               */
+    const opus_int8             pulses[],                           /* I    pulse signal                            */
+    opus_int                    length,                             /* I    length of input                         */
+    const opus_int              signalType,                         /* I    Signal type                             */
+    const opus_int              quantOffsetType,                    /* I    Quantization offset type                */
+    const opus_int              sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block        */
+);
+
+/* Decodes signs of excitation */
+void silk_decode_signs(
+    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure               */
+    opus_int16                  pulses[],                           /* I/O  pulse signal                            */
+    opus_int                    length,                             /* I    length of input                         */
+    const opus_int              signalType,                         /* I    Signal type                             */
+    const opus_int              quantOffsetType,                    /* I    Quantization offset type                */
+    const opus_int              sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block        */
+);
+
+/* Check encoder control struct */
+opus_int check_control_input(
+    silk_EncControlStruct        *encControl                    /* I    Control structure                           */
+);
+
+/* Control internal sampling rate */
+opus_int silk_control_audio_bandwidth(
+    silk_encoder_state          *psEncC,                        /* I/O  Pointer to Silk encoder state               */
+    silk_EncControlStruct       *encControl                     /* I    Control structure                           */
+);
+
+/* Control SNR of residual quantizer */
+opus_int silk_control_SNR(
+    silk_encoder_state          *psEncC,                        /* I/O  Pointer to Silk encoder state               */
+    opus_int32                  TargetRate_bps                  /* I    Target max bitrate (bps)                    */
+);
+
+/***************/
+/* Shell coder */
+/***************/
+
+/* Encode quantization indices of excitation */
+void silk_encode_pulses(
+    ec_enc                      *psRangeEnc,                    /* I/O  compressor data structure                   */
+    const opus_int              signalType,                     /* I    Signal type                                 */
+    const opus_int              quantOffsetType,                /* I    quantOffsetType                             */
+    opus_int8                   pulses[],                       /* I    quantization indices                        */
+    const opus_int              frame_length                    /* I    Frame length                                */
+);
+
+/* Shell encoder, operates on one shell code frame of 16 pulses */
+void silk_shell_encoder(
+    ec_enc                      *psRangeEnc,                    /* I/O  compressor data structure                   */
+    const opus_int              *pulses0                        /* I    data: nonnegative pulse amplitudes          */
+);
+
+/* Shell decoder, operates on one shell code frame of 16 pulses */
+void silk_shell_decoder(
+    opus_int16                  *pulses0,                       /* O    data: nonnegative pulse amplitudes          */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    const opus_int              pulses4                         /* I    number of pulses per pulse-subframe         */
+);
+
+/* Gain scalar quantization with hysteresis, uniform on log scale */
+void silk_gains_quant(
+    opus_int8                   ind[ MAX_NB_SUBFR ],            /* O    gain indices                                */
+    opus_int32                  gain_Q16[ MAX_NB_SUBFR ],       /* I/O  gains (quantized out)                       */
+    opus_int8                   *prev_ind,                      /* I/O  last index in previous frame                */
+    const opus_int              conditional,                    /* I    first gain is delta coded if 1              */
+    const opus_int              nb_subfr                        /* I    number of subframes                         */
+);
+
+/* Gains scalar dequantization, uniform on log scale */
+void silk_gains_dequant(
+    opus_int32                  gain_Q16[ MAX_NB_SUBFR ],       /* O    quantized gains                             */
+    const opus_int8             ind[ MAX_NB_SUBFR ],            /* I    gain indices                                */
+    opus_int8                   *prev_ind,                      /* I/O  last index in previous frame                */
+    const opus_int              conditional,                    /* I    first gain is delta coded if 1              */
+    const opus_int              nb_subfr                        /* I    number of subframes                          */
+);
+
+/* Compute unique identifier of gain indices vector */
+opus_int32 silk_gains_ID(                                       /* O    returns unique identifier of gains          */
+    const opus_int8             ind[ MAX_NB_SUBFR ],            /* I    gain indices                                */
+    const opus_int              nb_subfr                        /* I    number of subframes                         */
+);
+
+/* Interpolate two vectors */
+void silk_interpolate(
+    opus_int16                  xi[ MAX_LPC_ORDER ],            /* O    interpolated vector                         */
+    const opus_int16            x0[ MAX_LPC_ORDER ],            /* I    first vector                                */
+    const opus_int16            x1[ MAX_LPC_ORDER ],            /* I    second vector                               */
+    const opus_int              ifact_Q2,                       /* I    interp. factor, weight on 2nd vector        */
+    const opus_int              d                               /* I    number of parameters                        */
+);
+
+/* LTP tap quantizer */
+void silk_quant_LTP_gains(
+    opus_int16                  B_Q14[ MAX_NB_SUBFR * LTP_ORDER ],          /* O    Quantized LTP gains             */
+    opus_int8                   cbk_index[ MAX_NB_SUBFR ],                  /* O    Codebook Index                  */
+    opus_int8                   *periodicity_index,                         /* O    Periodicity Index               */
+    opus_int32                  *sum_gain_dB_Q7,                            /* I/O  Cumulative max prediction gain  */
+    opus_int                    *pred_gain_dB_Q7,                           /* O    LTP prediction gain             */
+    const opus_int32            XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I    Correlation matrix in Q18       */
+    const opus_int32            xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ],           /* I    Correlation vector in Q18       */
+    const opus_int              subfr_len,                                  /* I    Number of samples per subframe  */
+    const opus_int              nb_subfr,                                   /* I    Number of subframes             */
+    int                         arch                                        /* I    Run-time architecture           */
+);
+
+/* Entropy constrained matrix-weighted VQ, for a single input data vector */
+void silk_VQ_WMat_EC_c(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+);
+
+#if !defined(OVERRIDE_silk_VQ_WMat_EC)
+#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L, arch) \
+    ((void)(arch),silk_VQ_WMat_EC_c(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L))
+#endif
+
+/************************************/
+/* Noise shaping quantization (NSQ) */
+/************************************/
+
+void silk_NSQ_c(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#if !defined(OVERRIDE_silk_NSQ)
+#define silk_NSQ(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+#endif
+
+/* Noise shaping using delayed decision */
+void silk_NSQ_del_dec_c(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+#endif
+
+/************/
+/* Silk VAD */
+/************/
+/* Initialize the Silk VAD */
+opus_int silk_VAD_Init(                                         /* O    Return value, 0 if success                  */
+    silk_VAD_state              *psSilk_VAD                     /* I/O  Pointer to Silk VAD state                   */
+);
+
+/* Get speech activity level in Q8 */
+opus_int silk_VAD_GetSA_Q8_c(                                   /* O    Return value, 0 if success                  */
+    silk_encoder_state          *psEncC,                        /* I/O  Encoder state                               */
+    const opus_int16            pIn[]                           /* I    PCM input                                   */
+);
+
+#if !defined(OVERRIDE_silk_VAD_GetSA_Q8)
+#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_c(psEnC, pIn))
+#endif
+
+/* Low-pass filter with variable cutoff frequency based on  */
+/* piece-wise linear interpolation between elliptic filters */
+/* Start by setting transition_frame_no = 1;                */
+void silk_LP_variable_cutoff(
+    silk_LP_state               *psLP,                          /* I/O  LP filter state                             */
+    opus_int16                  *frame,                         /* I/O  Low-pass filtered output signal             */
+    const opus_int              frame_length                    /* I    Frame length                                */
+);
+
+/******************/
+/* NLSF Quantizer */
+/******************/
+/* Limit, stabilize, convert and quantize NLSFs */
+void silk_process_NLSFs(
+    silk_encoder_state          *psEncC,                            /* I/O  Encoder state                               */
+    opus_int16                  PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O    Prediction coefficients                     */
+    opus_int16                  pNLSF_Q15[         MAX_LPC_ORDER ], /* I/O  Normalized LSFs (quant out) (0 - (2^15-1))  */
+    const opus_int16            prev_NLSFq_Q15[    MAX_LPC_ORDER ]  /* I    Previous Normalized LSFs (0 - (2^15-1))     */
+);
+
+opus_int32 silk_NLSF_encode(                                    /* O    Returns RD value in Q25                     */
+          opus_int8             *NLSFIndices,                   /* I    Codebook path vector [ LPC_ORDER + 1 ]      */
+          opus_int16            *pNLSF_Q15,                     /* I/O  Quantized NLSF vector [ LPC_ORDER ]         */
+    const silk_NLSF_CB_struct   *psNLSF_CB,                     /* I    Codebook object                             */
+    const opus_int16            *pW_QW,                         /* I    NLSF weight vector [ LPC_ORDER ]            */
+    const opus_int              NLSF_mu_Q20,                    /* I    Rate weight for the RD optimization         */
+    const opus_int              nSurvivors,                     /* I    Max survivors after first stage             */
+    const opus_int              signalType                      /* I    Signal type: 0/1/2                          */
+);
+
+/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
+void silk_NLSF_VQ(
+    opus_int32                  err_Q26[],                      /* O    Quantization errors [K]                     */
+    const opus_int16            in_Q15[],                       /* I    Input vectors to be quantized [LPC_order]   */
+    const opus_uint8            pCB_Q8[],                       /* I    Codebook vectors [K*LPC_order]              */
+    const opus_int16            pWght_Q9[],                     /* I    Codebook weights [K*LPC_order]              */
+    const opus_int              K,                              /* I    Number of codebook vectors                  */
+    const opus_int              LPC_order                       /* I    Number of LPCs                              */
+);
+
+/* Delayed-decision quantizer for NLSF residuals */
+opus_int32 silk_NLSF_del_dec_quant(                             /* O    Returns RD value in Q25                     */
+    opus_int8                   indices[],                      /* O    Quantization indices [ order ]              */
+    const opus_int16            x_Q10[],                        /* I    Input [ order ]                             */
+    const opus_int16            w_Q5[],                         /* I    Weights [ order ]                           */
+    const opus_uint8            pred_coef_Q8[],                 /* I    Backward predictor coefs [ order ]          */
+    const opus_int16            ec_ix[],                        /* I    Indices to entropy coding tables [ order ]  */
+    const opus_uint8            ec_rates_Q5[],                  /* I    Rates []                                    */
+    const opus_int              quant_step_size_Q16,            /* I    Quantization step size                      */
+    const opus_int16            inv_quant_step_size_Q6,         /* I    Inverse quantization step size              */
+    const opus_int32            mu_Q20,                         /* I    R/D tradeoff                                */
+    const opus_int16            order                           /* I    Number of input values                      */
+);
+
+/* Unpack predictor values and indices for entropy coding tables */
+void silk_NLSF_unpack(
+          opus_int16            ec_ix[],                        /* O    Indices to entropy tables [ LPC_ORDER ]     */
+          opus_uint8            pred_Q8[],                      /* O    LSF predictor [ LPC_ORDER ]                 */
+    const silk_NLSF_CB_struct   *psNLSF_CB,                     /* I    Codebook object                             */
+    const opus_int              CB1_index                       /* I    Index of vector in first LSF codebook       */
+);
+
+/***********************/
+/* NLSF vector decoder */
+/***********************/
+void silk_NLSF_decode(
+          opus_int16            *pNLSF_Q15,                     /* O    Quantized NLSF vector [ LPC_ORDER ]         */
+          opus_int8             *NLSFIndices,                   /* I    Codebook path vector [ LPC_ORDER + 1 ]      */
+    const silk_NLSF_CB_struct   *psNLSF_CB                      /* I    Codebook object                             */
+);
+
+/****************************************************/
+/* Decoder Functions                                */
+/****************************************************/
+opus_int silk_reset_decoder(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state pointer                       */
+);
+
+opus_int silk_init_decoder(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state pointer                       */
+);
+
+/* Set decoder sampling rate */
+opus_int silk_decoder_set_fs(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state pointer                       */
+    opus_int                    fs_kHz,                         /* I    Sampling frequency (kHz)                    */
+    opus_int32                  fs_API_Hz                       /* I    API Sampling frequency (Hz)                 */
+);
+
+/****************/
+/* Decode frame */
+/****************/
+opus_int silk_decode_frame(
+    silk_decoder_state          *psDec,                         /* I/O  Pointer to Silk decoder state               */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int16                  pOut[],                         /* O    Pointer to output speech frame              */
+    opus_int32                  *pN,                            /* O    Pointer to size of output frame             */
+    opus_int                    lostFlag,                       /* I    0: no loss, 1 loss, 2 decode fec            */
+    opus_int                    condCoding,                     /* I    The type of conditional coding to use       */
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState              *lpcnet,
+#endif
+#ifdef ENABLE_OSCE
+    OSCEModel                   *osce_model,
+#endif
+    int                         arch                            /* I    Run-time architecture                       */
+);
+
+/* Decode indices from bitstream */
+void silk_decode_indices(
+    silk_decoder_state          *psDec,                         /* I/O  State                                       */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int                    FrameIndex,                     /* I    Frame number                                */
+    opus_int                    decode_LBRR,                    /* I    Flag indicating LBRR data is being decoded  */
+    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
+);
+
+/* Decode parameters from payload */
+void silk_decode_parameters(
+    silk_decoder_state          *psDec,                         /* I/O  State                                       */
+    silk_decoder_control        *psDecCtrl,                     /* I/O  Decoder control                             */
+    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
+);
+
+/* Core decoder. Performs inverse NSQ operation LTP + LPC */
+void silk_decode_core(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
+    silk_decoder_control        *psDecCtrl,                     /* I    Decoder control                             */
+    opus_int16                  xq[],                           /* O    Decoded speech                              */
+    const opus_int16            pulses[ MAX_FRAME_LENGTH ],     /* I    Pulse signal                                */
+    int                         arch                            /* I    Run-time architecture                       */
+);
+
+/* Decode quantization indices of excitation (Shell coding) */
+void silk_decode_pulses(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int16                  pulses[],                       /* O    Excitation signal                           */
+    const opus_int              signalType,                     /* I    Sigtype                                     */
+    const opus_int              quantOffsetType,                /* I    quantOffsetType                             */
+    const opus_int              frame_length                    /* I    Frame length                                */
+);
+
+/******************/
+/* CNG */
+/******************/
+
+/* Reset CNG */
+void silk_CNG_Reset(
+    silk_decoder_state          *psDec                          /* I/O  Decoder state                               */
+);
+
+/* Updates CNG estimate, and applies the CNG when packet was lost */
+void silk_CNG(
+    silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
+    silk_decoder_control        *psDecCtrl,                     /* I/O  Decoder control                             */
+    opus_int16                  frame[],                        /* I/O  Signal                                      */
+    opus_int                    length                          /* I    Length of residual                          */
+);
+
+/* Encoding of various parameters */
+void silk_encode_indices(
+    silk_encoder_state          *psEncC,                        /* I/O  Encoder state                               */
+    ec_enc                      *psRangeEnc,                    /* I/O  Compressor data structure                   */
+    opus_int                    FrameIndex,                     /* I    Frame number                                */
+    opus_int                    encode_LBRR,                    /* I    Flag indicating LBRR data is being encoded  */
+    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
+);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FIX.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FIX.h
new file mode 100644 (file)
index 0000000..53a97c5
--- /dev/null
@@ -0,0 +1,233 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MAIN_FIX_H
+#define SILK_MAIN_FIX_H
+
+#include "SigProc_FIX.h"
+#include "structs_FIX.h"
+#include "control.h"
+#include "main.h"
+#include "PLC.h"
+#include "debug.h"
+#include "entenc.h"
+
+#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
+   || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
+#endif
+
+
+#define silk_encoder_state_Fxx      silk_encoder_state_FIX
+#define silk_encode_do_VAD_Fxx      silk_encode_do_VAD_FIX
+#define silk_encode_frame_Fxx       silk_encode_frame_FIX
+
+#define QC  10
+#define QS  13
+
+/*********************/
+/* Encoder Functions */
+/*********************/
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+    silk_encoder_state_Fxx          state_Fxx[]                             /* I/O  Encoder states                                                              */
+);
+
+/* Encoder main function */
+void silk_encode_do_VAD_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
+    opus_int                        activity                                /* I    Decision of Opus voice activity detector                                    */
+);
+
+/* Encoder main function */
+opus_int silk_encode_frame_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
+    opus_int32                      *pnBytesOut,                            /* O    Pointer to number of payload bytes;                                         */
+    ec_enc                          *psRangeEnc,                            /* I/O  compressor data structure                                                   */
+    opus_int                        condCoding,                             /* I    The type of conditional coding to use                                       */
+    opus_int                        maxBits,                                /* I    If > 0: maximum number of output bits                                       */
+    opus_int                        useCBR                                  /* I    Flag to force constant-bitrate operation                                    */
+);
+
+/* Initializes the Silk encoder state */
+opus_int silk_init_encoder(
+    silk_encoder_state_Fxx          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
+    int                              arch                                   /* I    Run-time architecture                                                       */
+);
+
+/* Control the Silk encoder */
+opus_int silk_control_encoder(
+    silk_encoder_state_Fxx          *psEnc,                                 /* I/O  Pointer to Silk encoder state                                               */
+    silk_EncControlStruct           *encControl,                            /* I    Control structure                                                           */
+    const opus_int                  allow_bw_switch,                        /* I    Flag to allow switching audio bandwidth                                     */
+    const opus_int                  channelNb,                              /* I    Channel number                                                              */
+    const opus_int                  force_fs_kHz
+);
+
+/**************************/
+/* Noise shaping analysis */
+/**************************/
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state FIX                                                           */
+    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Encoder control FIX                                                         */
+    const opus_int16                *pitch_res,                             /* I    LPC residual from pitch analysis                                            */
+    const opus_int16                *x,                                     /* I    Input signal [ frame_length + la_shape ]                                    */
+    int                              arch                                   /* I    Run-time architecture                                                       */
+);
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FIX_c(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+);
+
+#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+        ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
+#endif
+
+/* Calculation of LTP state scaling */
+void silk_LTP_scale_ctrl_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  encoder state                                                               */
+    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
+    opus_int                        condCoding                              /* I    The type of conditional coding to use                                       */
+);
+
+/**********************************************/
+/* Prediction Analysis                        */
+/**********************************************/
+/* Find pitch lags */
+void silk_find_pitch_lags_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  encoder state                                                               */
+    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
+    opus_int16                      res[],                                  /* O    residual                                                                    */
+    const opus_int16                x[],                                    /* I    Speech signal                                                               */
+    int                             arch                                    /* I    Run-time architecture                                                       */
+);
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  encoder state                                                               */
+    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
+    const opus_int16                res_pitch[],                            /* I    Residual from pitch analysis                                                */
+    const opus_int16                x[],                                    /* I    Speech signal                                                               */
+    opus_int                        condCoding                              /* I    The type of conditional coding to use                                       */
+);
+
+/* LPC analysis */
+void silk_find_LPC_FIX(
+    silk_encoder_state              *psEncC,                                /* I/O  Encoder state                                                               */
+    opus_int16                      NLSF_Q15[],                             /* O    NLSFs                                                                       */
+    const opus_int16                x[],                                    /* I    Input signal                                                                */
+    const opus_int32                minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
+);
+
+/* LTP analysis */
+void silk_find_LTP_FIX(
+    opus_int32                      XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Correlation matrix                                               */
+    opus_int32                      xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ],  /* O    Correlation vector                                                          */
+    const opus_int16                r_lpc[],                                /* I    Residual signal after LPC                                                   */
+    const opus_int                  lag[ MAX_NB_SUBFR ],                    /* I    LTP lags                                                                    */
+    const opus_int                  subfr_length,                           /* I    Subframe length                                                             */
+    const opus_int                  nb_subfr,                               /* I    Number of subframes                                                         */
+    int                             arch                                    /* I    Run-time architecture                                                       */
+);
+
+void silk_LTP_analysis_filter_FIX(
+    opus_int16                      *LTP_res,                               /* O    LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length )  */
+    const opus_int16                *x,                                     /* I    Pointer to input signal with at least max( pitchL ) preceding samples       */
+    const opus_int16                LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I    LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe                   */
+    const opus_int                  pitchL[ MAX_NB_SUBFR ],                 /* I    Pitch lag, one for each subframe                                            */
+    const opus_int32                invGains_Q16[ MAX_NB_SUBFR ],           /* I    Inverse quantization gains, one for each subframe                           */
+    const opus_int                  subfr_length,                           /* I    Length of each subframe                                                     */
+    const opus_int                  nb_subfr,                               /* I    Number of subframes                                                         */
+    const opus_int                  pre_length                              /* I    Length of the preceding samples starting at &x[0] for each subframe         */
+);
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order   */
+/* of preceding samples                                                                 */
+void silk_residual_energy_FIX(
+          opus_int32                nrgs[ MAX_NB_SUBFR ],                   /* O    Residual energy per subframe                                                */
+          opus_int                  nrgsQ[ MAX_NB_SUBFR ],                  /* O    Q value per subframe                                                        */
+    const opus_int16                x[],                                    /* I    Input signal                                                                */
+          opus_int16                a_Q12[ 2 ][ MAX_LPC_ORDER ],            /* I    AR coefs for each frame half                                                */
+    const opus_int32                gains[ MAX_NB_SUBFR ],                  /* I    Quantization gains                                                          */
+    const opus_int                  subfr_length,                           /* I    Subframe length                                                             */
+    const opus_int                  nb_subfr,                               /* I    Number of subframes                                                         */
+    const opus_int                  LPC_order,                              /* I    LPC order                                                                   */
+    int                             arch                                    /* I    Run-time architecture                                                       */
+);
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+opus_int32 silk_residual_energy16_covar_FIX(
+    const opus_int16                *c,                                     /* I    Prediction vector                                                           */
+    const opus_int32                *wXX,                                   /* I    Correlation matrix                                                          */
+    const opus_int32                *wXx,                                   /* I    Correlation vector                                                          */
+    opus_int32                      wxx,                                    /* I    Signal energy                                                               */
+    opus_int                        D,                                      /* I    Dimension                                                                   */
+    opus_int                        cQ                                      /* I    Q value for c vector 0 - 15                                                 */
+);
+
+/* Processing of gains */
+void silk_process_gains_FIX(
+    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
+    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Encoder control                                                             */
+    opus_int                        condCoding                              /* I    The type of conditional coding to use                                       */
+);
+
+/******************/
+/* Linear Algebra */
+/******************/
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FIX(
+    const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
+    const opus_int                  L,                                      /* I    Length of vectors                                                           */
+    const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
+    opus_int32                      *XX,                                    /* O    Pointer to X'*X correlation matrix [ order x order ]                        */
+    opus_int32                      *nrg,                                   /* O    Energy of x vector                                                          */
+    opus_int                        *rshifts,                               /* O    Right shifts of correlations                                                */
+    int                              arch                                   /* I    Run-time architecture                                                       */
+);
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FIX(
+    const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
+    const opus_int16                *t,                                     /* I    Target vector [L]                                                           */
+    const opus_int                  L,                                      /* I    Length of vectors                                                           */
+    const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
+    opus_int32                      *Xt,                                    /* O    Pointer to X'*t correlation vector [order]                                  */
+    const opus_int                  rshifts,                                /* I    Right shifts of correlations                                                */
+    int                             arch                                    /* I    Run-time architecture                                                       */
+);
+
+#endif /* SILK_MAIN_FIX_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FLP.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_FLP.h
new file mode 100644 (file)
index 0000000..8173bb3
--- /dev/null
@@ -0,0 +1,282 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_MAIN_FLP_H
+#define SILK_MAIN_FLP_H
+
+#include "SigProc_FLP.h"
+#include "SigProc_FIX.h"
+#include "structs_FLP.h"
+#include "main.h"
+#include "define.h"
+#include "debug.h"
+#include "entenc.h"
+
+
+#define silk_encoder_state_Fxx      silk_encoder_state_FLP
+#define silk_encode_do_VAD_Fxx      silk_encode_do_VAD_FLP
+#define silk_encode_frame_Fxx       silk_encode_frame_FLP
+
+/*********************/
+/* Encoder Functions */
+/*********************/
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+    silk_encoder_state_Fxx          state_Fxx[]                         /* I/O  Encoder states                              */
+);
+
+/* Encoder main function */
+void silk_encode_do_VAD_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    opus_int                        activity                            /* I    Decision of Opus voice activity detector    */
+);
+
+/* Encoder main function */
+opus_int silk_encode_frame_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    opus_int32                      *pnBytesOut,                        /* O    Number of payload bytes;                    */
+    ec_enc                          *psRangeEnc,                        /* I/O  compressor data structure                   */
+    opus_int                        condCoding,                         /* I    The type of conditional coding to use       */
+    opus_int                        maxBits,                            /* I    If > 0: maximum number of output bits       */
+    opus_int                        useCBR                              /* I    Flag to force constant-bitrate operation    */
+);
+
+/* Initializes the Silk encoder state */
+opus_int silk_init_encoder(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    int                              arch                               /* I    Run-tim architecture                        */
+);
+
+/* Control the Silk encoder */
+opus_int silk_control_encoder(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Pointer to Silk encoder state FLP           */
+    silk_EncControlStruct           *encControl,                        /* I    Control structure                           */
+    const opus_int                  allow_bw_switch,                    /* I    Flag to allow switching audio bandwidth     */
+    const opus_int                  channelNb,                          /* I    Channel number                              */
+    const opus_int                  force_fs_kHz
+);
+
+/**************************/
+/* Noise shaping analysis */
+/**************************/
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
+    const silk_float                *x                                  /* I    Input signal [frame_length + la_shape]      */
+);
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FLP(
+    silk_float                      *corr,                              /* O    Result [order + 1]                          */
+    const silk_float                *input,                             /* I    Input data to correlate                     */
+    const silk_float                warping,                            /* I    Warping coefficient                         */
+    const opus_int                  length,                             /* I    Length of input                             */
+    const opus_int                  order                               /* I    Correlation order (even)                    */
+);
+
+/* Calculation of LTP state scaling */
+void silk_LTP_scale_ctrl_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+);
+
+/**********************************************/
+/* Prediction Analysis                        */
+/**********************************************/
+/* Find pitch lags */
+void silk_find_pitch_lags_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    silk_float                      res[],                              /* O    Residual                                    */
+    const silk_float                x[],                                /* I    Speech signal                               */
+    int                             arch                                /* I    Run-time architecture                       */
+);
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    const silk_float                res_pitch[],                        /* I    Residual from pitch analysis                */
+    const silk_float                x[],                                /* I    Speech signal                               */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+);
+
+/* LPC analysis */
+void silk_find_LPC_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
+    opus_int16                      NLSF_Q15[],                         /* O    NLSFs                                       */
+    const silk_float                x[],                                /* I    Input signal                                */
+    const silk_float                minInvGain,                         /* I    Prediction gain from LTP (dB)               */
+    int                             arch
+);
+
+/* LTP analysis */
+void silk_find_LTP_FLP(
+    silk_float                      XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization         */
+    silk_float                      xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* O    Weight for LTP quantization                 */
+    const silk_float                r_ptr[],                            /* I    LPC residual                                */
+    const opus_int                  lag[  MAX_NB_SUBFR ],               /* I    LTP lags                                    */
+    const opus_int                  subfr_length,                       /* I    Subframe length                             */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    int                             arch
+);
+
+void silk_LTP_analysis_filter_FLP(
+    silk_float                      *LTP_res,                           /* O    LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */
+    const silk_float                *x,                                 /* I    Input signal, with preceding samples        */
+    const silk_float                B[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    LTP coefficients for each subframe          */
+    const opus_int                  pitchL[   MAX_NB_SUBFR ],           /* I    Pitch lags                                  */
+    const silk_float                invGains[ MAX_NB_SUBFR ],           /* I    Inverse quantization gains                  */
+    const opus_int                  subfr_length,                       /* I    Length of each subframe                     */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    const opus_int                  pre_length                          /* I    Preceding samples for each subframe         */
+);
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order   */
+/* of preceding samples                                                                 */
+void silk_residual_energy_FLP(
+    silk_float                      nrgs[ MAX_NB_SUBFR ],               /* O    Residual energy per subframe                */
+    const silk_float                x[],                                /* I    Input signal                                */
+    silk_float                      a[ 2 ][ MAX_LPC_ORDER ],            /* I    AR coefs for each frame half                */
+    const silk_float                gains[],                            /* I    Quantization gains                          */
+    const opus_int                  subfr_length,                       /* I    Subframe length                             */
+    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    const opus_int                  LPC_order                           /* I    LPC order                                   */
+);
+
+/* 16th order LPC analysis filter */
+void silk_LPC_analysis_filter_FLP(
+    silk_float                      r_LPC[],                            /* O    LPC residual signal                         */
+    const silk_float                PredCoef[],                         /* I    LPC coefficients                            */
+    const silk_float                s[],                                /* I    Input signal                                */
+    const opus_int                  length,                             /* I    Length of input signal                      */
+    const opus_int                  Order                               /* I    LPC order                                   */
+);
+
+/* LTP tap quantizer */
+void silk_quant_LTP_gains_FLP(
+    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    Quantized LTP gains                         */
+    opus_int8                       cbk_index[ MAX_NB_SUBFR ],          /* O    Codebook index                              */
+    opus_int8                       *periodicity_index,                 /* O    Periodicity index                           */
+    opus_int32                      *sum_log_gain_Q7,                   /* I/O  Cumulative max prediction gain  */
+    silk_float                      *pred_gain_dB,                      /* O    LTP prediction gain                         */
+    const silk_float                XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Correlation matrix                  */
+    const silk_float                xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* I    Correlation vector                          */
+    const opus_int                  subfr_len,                          /* I    Number of samples per subframe              */
+    const opus_int                  nb_subfr,                           /* I    Number of subframes                         */
+    int                             arch                                /* I    Run-time architecture                       */
+);
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+silk_float silk_residual_energy_covar_FLP(                              /* O    Weighted residual energy                    */
+    const silk_float                *c,                                 /* I    Filter coefficients                         */
+    silk_float                      *wXX,                               /* I/O  Weighted correlation matrix, reg. out       */
+    const silk_float                *wXx,                               /* I    Weighted correlation vector                 */
+    const silk_float                wxx,                                /* I    Weighted correlation value                  */
+    const opus_int                  D                                   /* I    Dimension                                   */
+);
+
+/* Processing of gains */
+void silk_process_gains_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    opus_int                        condCoding                          /* I    The type of conditional coding to use       */
+);
+
+/******************/
+/* Linear Algebra */
+/******************/
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FLP(
+    const silk_float                *x,                                 /* I    x vector [ L+order-1 ] used to create X     */
+    const opus_int                  L,                                  /* I    Length of vectors                           */
+    const opus_int                  Order,                              /* I    Max lag for correlation                     */
+    silk_float                      *XX,                                /* O    X'*X correlation matrix [order x order]     */
+    int                             arch
+);
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FLP(
+    const silk_float                *x,                                 /* I    x vector [L+order-1] used to create X       */
+    const silk_float                *t,                                 /* I    Target vector [L]                           */
+    const opus_int                  L,                                  /* I    Length of vecors                            */
+    const opus_int                  Order,                              /* I    Max lag for correlation                     */
+    silk_float                      *Xt,                                /* O    X'*t correlation vector [order]             */
+    int                             arch
+);
+
+/* Apply sine window to signal vector.  */
+/* Window types:                        */
+/*  1 -> sine window from 0 to pi/2     */
+/*  2 -> sine window from pi/2 to pi    */
+void silk_apply_sine_window_FLP(
+    silk_float                      px_win[],                           /* O    Pointer to windowed signal                  */
+    const silk_float                px[],                               /* I    Pointer to input signal                     */
+    const opus_int                  win_type,                           /* I    Selects a window type                       */
+    const opus_int                  length                              /* I    Window length, multiple of 4                */
+);
+
+/* Wrapper functions. Call flp / fix code */
+
+/* Convert AR filter coefficients to NLSF parameters */
+void silk_A2NLSF_FLP(
+    opus_int16                      *NLSF_Q15,                          /* O    NLSF vector      [ LPC_order ]              */
+    const silk_float                *pAR,                               /* I    LPC coefficients [ LPC_order ]              */
+    const opus_int                  LPC_order                           /* I    LPC order                                   */
+);
+
+/* Convert NLSF parameters to AR prediction filter coefficients */
+void silk_NLSF2A_FLP(
+    silk_float                      *pAR,                               /* O    LPC coefficients [ LPC_order ]              */
+    const opus_int16                *NLSF_Q15,                          /* I    NLSF vector      [ LPC_order ]              */
+    const opus_int                  LPC_order,                          /* I    LPC order                                   */
+    int                             arch                                /* I    Run-time architecture                       */
+);
+
+/* Limit, stabilize, and quantize NLSFs */
+void silk_process_NLSFs_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
+    silk_float                      PredCoef[ 2 ][ MAX_LPC_ORDER ],     /* O    Prediction coefficients                     */
+    opus_int16                      NLSF_Q15[      MAX_LPC_ORDER ],     /* I/O  Normalized LSFs (quant out) (0 - (2^15-1))  */
+    const opus_int16                prev_NLSF_Q15[ MAX_LPC_ORDER ]      /* I    Previous Normalized LSFs (0 - (2^15-1))     */
+);
+
+/* Floating-point Silk NSQ wrapper      */
+void silk_NSQ_wrapper_FLP(
+    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
+    silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
+    SideInfoIndices                 *psIndices,                         /* I/O  Quantization indices                        */
+    silk_nsq_state                  *psNSQ,                             /* I/O  Noise Shaping Quantzation state             */
+    opus_int8                       pulses[],                           /* O    Quantized pulse signal                      */
+    const silk_float                x[]                                 /* I    Prefiltered input signal                    */
+);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/main_sse.h
new file mode 100644 (file)
index 0000000..b254d53
--- /dev/null
@@ -0,0 +1,299 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MAIN_SSE_H
+# define MAIN_SSE_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+
+void silk_VQ_WMat_EC_sse4_1(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+);
+
+#  if defined OPUS_X86_PRESUME_SSE4_1
+
+#   define OVERRIDE_silk_VQ_WMat_EC
+#   define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                           subfr_len, max_gain_Q7, L, arch) \
+    ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                          subfr_len, max_gain_Q7, L))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+);
+
+#   define OVERRIDE_silk_VQ_WMat_EC
+#   define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                           subfr_len, max_gain_Q7, L, arch) \
+    ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                          subfr_len, max_gain_Q7, L))
+
+#  endif
+
+void silk_NSQ_sse4_1(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#  if defined OPUS_X86_PRESUME_SSE4_1
+
+#   define OVERRIDE_silk_NSQ
+#   define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#   define OVERRIDE_silk_NSQ
+#   define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  endif
+
+void silk_NSQ_del_dec_sse4_1(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+void silk_NSQ_del_dec_avx2(
+    const silk_encoder_state *psEncC,                            /* I    Encoder State               */
+    silk_nsq_state *NSQ,                                         /* I/O  NSQ state                   */
+    SideInfoIndices *psIndices,                                  /* I/O  Quantization Indices        */
+    const opus_int16 x16[],                                      /* I    Input                       */
+    opus_int8 pulses[],                                          /* O    Quantized pulse signal      */
+    const opus_int16 *PredCoef_Q12,                              /* I    Short term prediction coefs */
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],      /* I    Long term prediction coefs  */
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER], /* I    Noise shaping coefs         */
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],              /* I    Long term shaping coefs     */
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],                       /* I    Spectral tilt               */
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],                   /* I    Low frequency shaping coefs */
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],                    /* I    Quantization step sizes     */
+    const opus_int32 pitchL[MAX_NB_SUBFR],                       /* I    Pitch lags                  */
+    const opus_int Lambda_Q10,                                   /* I    Rate/distortion tradeoff    */
+    const opus_int LTP_scale_Q14                                 /* I    LTP state scaling           */
+);
+
+#  if defined (OPUS_X86_PRESUME_AVX2)
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_del_dec_avx2(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined (OPUS_X86_PRESUME_SSE4_1) && !defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  endif
+
+void silk_noise_shape_quantizer(
+    silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
+    opus_int            signalType,             /* I    Signal type                     */
+    const opus_int32    x_sc_Q10[],             /* I                                    */
+    opus_int8           pulses[],               /* O                                    */
+    opus_int16          xq[],                   /* O                                    */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP state                       */
+    const opus_int16    a_Q12[],                /* I    Short term prediction coefs     */
+    const opus_int16    b_Q14[],                /* I    Long term prediction coefs      */
+    const opus_int16    AR_shp_Q13[],           /* I    Noise shaping AR coefs          */
+    opus_int            lag,                    /* I    Pitch lag                       */
+    opus_int32          HarmShapeFIRPacked_Q14, /* I                                    */
+    opus_int            Tilt_Q14,               /* I    Spectral tilt                   */
+    opus_int32          LF_shp_Q14,             /* I                                    */
+    opus_int32          Gain_Q16,               /* I                                    */
+    opus_int            Lambda_Q10,             /* I                                    */
+    opus_int            offset_Q10,             /* I                                    */
+    opus_int            length,                 /* I    Input length                    */
+    opus_int            shapingLPCOrder,        /* I    Noise shaping AR filter order   */
+    opus_int            predictLPCOrder,        /* I    Prediction filter order         */
+    int                 arch                    /* I    Architecture                    */
+);
+
+/**************************/
+/* Noise level estimation */
+/**************************/
+void silk_VAD_GetNoiseLevels(
+    const opus_int32            pX[ VAD_N_BANDS ],  /* I    subband energies                            */
+    silk_VAD_state              *psSilk_VAD         /* I/O  Pointer to Silk VAD state                   */
+);
+
+opus_int silk_VAD_GetSA_Q8_sse4_1(
+    silk_encoder_state *psEnC,
+    const opus_int16   pIn[]
+);
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_VAD_GetSA_Q8
+#   define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
+     silk_encoder_state *psEnC,
+     const opus_int16   pIn[]);
+
+#   define OVERRIDE_silk_VAD_GetSA_Q8
+#   define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
+      ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
+
+#  endif
+
+#ifndef FIXED_POINT
+double silk_inner_product_FLP_avx2(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+);
+
+#if defined (OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_avx2(data1, data2, dataSize))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+extern double (*const SILK_INNER_PRODUCT_FLP_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+);
+
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,(*SILK_INNER_PRODUCT_FLP_IMPL[(arch) & OPUS_ARCHMASK])(data1, data2, dataSize))
+
+#endif
+#endif
+
+# endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_defines.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_defines.h
new file mode 100644 (file)
index 0000000..ee84462
--- /dev/null
@@ -0,0 +1,87 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_PE_DEFINES_H
+#define SILK_PE_DEFINES_H
+
+#include "SigProc_FIX.h"
+
+/********************************************************/
+/* Definitions for pitch estimator                      */
+/********************************************************/
+
+#define PE_MAX_FS_KHZ               16 /* Maximum sampling frequency used */
+
+#define PE_MAX_NB_SUBFR             4
+#define PE_SUBFR_LENGTH_MS          5   /* 5 ms */
+
+#define PE_LTP_MEM_LENGTH_MS        ( 4 * PE_SUBFR_LENGTH_MS )
+
+#define PE_MAX_FRAME_LENGTH_MS      ( PE_LTP_MEM_LENGTH_MS + PE_MAX_NB_SUBFR * PE_SUBFR_LENGTH_MS )
+#define PE_MAX_FRAME_LENGTH         ( PE_MAX_FRAME_LENGTH_MS * PE_MAX_FS_KHZ )
+#define PE_MAX_FRAME_LENGTH_ST_1    ( PE_MAX_FRAME_LENGTH >> 2 )
+#define PE_MAX_FRAME_LENGTH_ST_2    ( PE_MAX_FRAME_LENGTH >> 1 )
+
+#define PE_MAX_LAG_MS               18           /* 18 ms -> 56 Hz */
+#define PE_MIN_LAG_MS               2            /* 2 ms -> 500 Hz */
+#define PE_MAX_LAG                  ( PE_MAX_LAG_MS * PE_MAX_FS_KHZ )
+#define PE_MIN_LAG                  ( PE_MIN_LAG_MS * PE_MAX_FS_KHZ )
+
+#define PE_D_SRCH_LENGTH            24
+
+#define PE_NB_STAGE3_LAGS           5
+
+#define PE_NB_CBKS_STAGE2           3
+#define PE_NB_CBKS_STAGE2_EXT       11
+
+#define PE_NB_CBKS_STAGE3_MAX       34
+#define PE_NB_CBKS_STAGE3_MID       24
+#define PE_NB_CBKS_STAGE3_MIN       16
+
+#define PE_NB_CBKS_STAGE3_10MS      12
+#define PE_NB_CBKS_STAGE2_10MS      3
+
+#define PE_SHORTLAG_BIAS            0.2f    /* for logarithmic weighting    */
+#define PE_PREVLAG_BIAS             0.2f    /* for logarithmic weighting    */
+#define PE_FLATCONTOUR_BIAS         0.05f
+
+#define SILK_PE_MIN_COMPLEX         0
+#define SILK_PE_MID_COMPLEX         1
+#define SILK_PE_MAX_COMPLEX         2
+
+/* Tables for 20 ms frames */
+extern const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ];
+extern const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ];
+extern const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ];
+extern const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ];
+
+/* Tables for 10 ms frames */
+extern const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ 3 ];
+extern const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 12 ];
+extern const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ];
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_tables.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/pitch_est_tables.c
new file mode 100644 (file)
index 0000000..81a8bac
--- /dev/null
@@ -0,0 +1,99 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "typedef.h"
+#include "pitch_est_defines.h"
+
+const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ PE_NB_CBKS_STAGE2_10MS ] =
+{
+    {0, 1, 0},
+    {0, 0, 1}
+};
+
+const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ PE_NB_CBKS_STAGE3_10MS ] =
+{
+    { 0, 0, 1,-1, 1,-1, 2,-2, 2,-2, 3,-3},
+    { 0, 1, 0, 1,-1, 2,-1, 2,-2, 3,-2, 3}
+};
+
+const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ] =
+{
+    {-3, 7},
+    {-2, 7}
+};
+
+const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ] =
+{
+    {0, 2,-1,-1,-1, 0, 0, 1, 1, 0, 1},
+    {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+    {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0},
+    {0,-1, 2, 1, 0, 1, 1, 0, 0,-1,-1}
+};
+
+const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ] =
+{
+    {0, 0, 1,-1, 0, 1,-1, 0,-1, 1,-2, 2,-2,-2, 2,-3, 2, 3,-3,-4, 3,-4, 4, 4,-5, 5,-6,-5, 6,-7, 6, 5, 8,-9},
+    {0, 0, 1, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 0, 1,-1,-1, 1,-1, 2, 1,-1, 2,-2,-2, 2,-2, 2, 2, 3,-3},
+    {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,-1, 1, 0, 0, 2, 1,-1, 2,-1,-1, 2,-1, 2, 2,-1, 3,-2,-2,-2, 3},
+    {0, 1, 0, 0, 1, 0, 1,-1, 2,-1, 2,-1, 2, 3,-2, 3,-2,-2, 4, 4,-3, 5,-3,-4, 6,-4, 6, 5,-5, 8,-6,-5,-7, 9}
+};
+
+const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ] =
+{
+    /* Lags to search for low number of stage3 cbks */
+    {
+        {-5,8},
+        {-1,6},
+        {-1,6},
+        {-4,10}
+    },
+    /* Lags to search for middle number of stage3 cbks */
+    {
+        {-6,10},
+        {-2,6},
+        {-1,6},
+        {-5,10}
+    },
+    /* Lags to search for max number of stage3 cbks */
+    {
+        {-9,12},
+        {-3,7},
+        {-2,7},
+        {-7,13}
+    }
+};
+
+const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ] =
+{
+    PE_NB_CBKS_STAGE3_MIN,
+    PE_NB_CBKS_STAGE3_MID,
+    PE_NB_CBKS_STAGE3_MAX
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler.c
new file mode 100644 (file)
index 0000000..2fe6eaa
--- /dev/null
@@ -0,0 +1,224 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Matrix of resampling methods used:
+ *                                 Fs_out (kHz)
+ *                        8      12     16     24     48
+ *
+ *               8        C      UF     U      UF     UF
+ *              12        AF     C      UF     U      UF
+ * Fs_in (kHz)  16        D      AF     C      UF     UF
+ *              24        AF     D      AF     C      U
+ *              48        AF     AF     AF     D      C
+ *
+ * C   -> Copy (no resampling)
+ * D   -> Allpass-based 2x downsampling
+ * U   -> Allpass-based 2x upsampling
+ * UF  -> Allpass-based 2x upsampling followed by FIR interpolation
+ * AF  -> AR2 filter followed by FIR interpolation
+ */
+
+#include "resampler_private.h"
+
+/* Tables with delay compensation values to equalize total delay for different modes */
+static const opus_int8 delay_matrix_enc[ 6 ][ 3 ] = {
+/* in  \ out  8  12  16 */
+/*  8 */   {  6,  0,  3 },
+/* 12 */   {  0,  7,  3 },
+/* 16 */   {  0,  1, 10 },
+/* 24 */   {  0,  2,  6 },
+/* 48 */   { 18, 10, 12 },
+/* 96 */   {  0,  0,  44 }
+};
+
+static const opus_int8 delay_matrix_dec[ 3 ][ 6 ] = {
+/* in  \ out  8  12  16  24  48  96*/
+/*  8 */   {  4,  0,  2,  0,  0,  0 },
+/* 12 */   {  0,  9,  4,  7,  4,  4 },
+/* 16 */   {  0,  3, 12,  7,  7,  7 }
+};
+
+/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */
+#define rateID(R) IMIN(5, ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ))
+
+#define USE_silk_resampler_copy                     (0)
+#define USE_silk_resampler_private_up2_HQ_wrapper   (1)
+#define USE_silk_resampler_private_IIR_FIR          (2)
+#define USE_silk_resampler_private_down_FIR         (3)
+
+/* Initialize/reset the resampler state for a given pair of input/output sampling rates */
+opus_int silk_resampler_init(
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int32                  Fs_Hz_in,           /* I    Input sampling rate (Hz)                                    */
+    opus_int32                  Fs_Hz_out,          /* I    Output sampling rate (Hz)                                   */
+    opus_int                    forEnc              /* I    If 1: encoder; if 0: decoder                                */
+)
+{
+    opus_int up2x;
+
+    /* Clear state */
+    silk_memset( S, 0, sizeof( silk_resampler_state_struct ) );
+
+    /* Input checking */
+    if( forEnc ) {
+        if( ( Fs_Hz_in  != 8000 && Fs_Hz_in  != 12000 && Fs_Hz_in  != 16000 && Fs_Hz_in  != 24000 && Fs_Hz_in  != 48000
+#ifdef ENABLE_QEXT
+                  && Fs_Hz_in != 96000
+#endif
+              ) ||
+            ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
+            celt_assert( 0 );
+            return -1;
+        }
+        S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
+    } else {
+        if( ( Fs_Hz_in  != 8000 && Fs_Hz_in  != 12000 && Fs_Hz_in  != 16000 ) ||
+            ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000
+#ifdef ENABLE_QEXT
+                  && Fs_Hz_out != 96000
+#endif
+                  ) ) {
+            celt_assert( 0 );
+            return -1;
+        }
+        S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
+    }
+
+    S->Fs_in_kHz  = silk_DIV32_16( Fs_Hz_in,  1000 );
+    S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 );
+
+    /* Number of samples processed per batch */
+    S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS;
+
+    /* Find resampler with the right sampling ratio */
+    up2x = 0;
+    if( Fs_Hz_out > Fs_Hz_in ) {
+        /* Upsample */
+        if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) {                            /* Fs_out : Fs_in = 2 : 1 */
+            /* Special case: directly use 2x upsampler */
+            S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper;
+        } else {
+            /* Default resampler */
+            S->resampler_function = USE_silk_resampler_private_IIR_FIR;
+            up2x = 1;
+        }
+    } else if ( Fs_Hz_out < Fs_Hz_in ) {
+        /* Downsample */
+         S->resampler_function = USE_silk_resampler_private_down_FIR;
+        if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) {             /* Fs_out : Fs_in = 3 : 4 */
+            S->FIR_Fracs = 3;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
+            S->Coefs = silk_Resampler_3_4_COEFS;
+        } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) {      /* Fs_out : Fs_in = 2 : 3 */
+            S->FIR_Fracs = 2;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
+            S->Coefs = silk_Resampler_2_3_COEFS;
+        } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 2 */
+            S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1;
+            S->Coefs = silk_Resampler_1_2_COEFS;
+        } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 3 */
+            S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+            S->Coefs = silk_Resampler_1_3_COEFS;
+        } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 4 */
+            S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+            S->Coefs = silk_Resampler_1_4_COEFS;
+        } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 6 */
+            S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+            S->Coefs = silk_Resampler_1_6_COEFS;
+        } else {
+            /* None available */
+            celt_assert( 0 );
+            return -1;
+        }
+    } else {
+        /* Input and output sampling rates are equal: copy */
+        S->resampler_function = USE_silk_resampler_copy;
+    }
+
+    /* Ratio of input/output samples */
+    S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 );
+    /* Make sure the ratio is rounded up */
+    while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) {
+        S->invRatio_Q16++;
+    }
+
+    return 0;
+}
+
+/* Resampler: convert from one sampling rate to another */
+/* Input and output sampling rate are at most 48000 Hz  */
+opus_int silk_resampler(
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int16                  out[],              /* O    Output signal                                               */
+    const opus_int16            in[],               /* I    Input signal                                                */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+)
+{
+    opus_int nSamples;
+
+    /* Need at least 1 ms of input data */
+    celt_assert( inLen >= S->Fs_in_kHz );
+    /* Delay can't exceed the 1 ms of buffering */
+    celt_assert( S->inputDelay <= S->Fs_in_kHz );
+
+    nSamples = S->Fs_in_kHz - S->inputDelay;
+
+    /* Copy to delay buffer */
+    silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) );
+
+    switch( S->resampler_function ) {
+        case USE_silk_resampler_private_up2_HQ_wrapper:
+            silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+            break;
+        case USE_silk_resampler_private_IIR_FIR:
+            silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+            break;
+        case USE_silk_resampler_private_down_FIR:
+            silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+            break;
+        default:
+            silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) );
+            silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) );
+    }
+
+    /* Copy to delay buffer */
+    silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) );
+
+    return 0;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2.c
new file mode 100644 (file)
index 0000000..febe495
--- /dev/null
@@ -0,0 +1,73 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_rom.h"
+
+/* Downsample by a factor 2 */
+void silk_resampler_down2(
+    opus_int32                  *S,                 /* I/O  State vector [ 2 ]                                          */
+    opus_int16                  *out,               /* O    Output signal [ floor(len/2) ]                              */
+    const opus_int16            *in,                /* I    Input signal [ len ]                                        */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+)
+{
+    opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 );
+    opus_int32 in32, out32, Y, X;
+
+    celt_assert( silk_resampler_down2_0 > 0 );
+    celt_assert( silk_resampler_down2_1 < 0 );
+
+    /* Internal variables and state are in Q10 format */
+    for( k = 0; k < len2; k++ ) {
+        /* Convert to Q10 */
+        in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 );
+
+        /* All-pass section for even input sample */
+        Y      = silk_SUB32( in32, S[ 0 ] );
+        X      = silk_SMLAWB( Y, Y, silk_resampler_down2_1 );
+        out32  = silk_ADD32( S[ 0 ], X );
+        S[ 0 ] = silk_ADD32( in32, X );
+
+        /* Convert to Q10 */
+        in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 );
+
+        /* All-pass section for odd input sample, and add to output of previous section */
+        Y      = silk_SUB32( in32, S[ 1 ] );
+        X      = silk_SMULWB( Y, silk_resampler_down2_0 );
+        out32  = silk_ADD32( out32, S[ 1 ] );
+        out32  = silk_ADD32( out32, X );
+        S[ 1 ] = silk_ADD32( in32, X );
+
+        /* Add, convert back to int16 and store to output */
+        out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32, 11 ) );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2_3.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_down2_3.c
new file mode 100644 (file)
index 0000000..4342614
--- /dev/null
@@ -0,0 +1,103 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+#define ORDER_FIR                   4
+
+/* Downsample by a factor 2/3, low quality */
+void silk_resampler_down2_3(
+    opus_int32                  *S,                 /* I/O  State vector [ 6 ]                                          */
+    opus_int16                  *out,               /* O    Output signal [ floor(2*inLen/3) ]                          */
+    const opus_int16            *in,                /* I    Input signal [ inLen ]                                      */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
+)
+{
+    opus_int32 nSamplesIn, counter, res_Q6;
+    VARDECL( opus_int32, buf );
+    opus_int32 *buf_ptr;
+    SAVE_STACK;
+
+    ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 );
+
+    /* Copy buffered samples to start of buffer */
+    silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) );
+
+    /* Iterate over blocks of frameSizeIn input samples */
+    while( 1 ) {
+        nSamplesIn = silk_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN );
+
+        /* Second-order AR filter (output in Q8) */
+        silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in,
+            silk_Resampler_2_3_COEFS_LQ, nSamplesIn );
+
+        /* Interpolate filtered signal */
+        buf_ptr = buf;
+        counter = nSamplesIn;
+        while( counter > 2 ) {
+            /* Inner product */
+            res_Q6 = silk_SMULWB(         buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
+
+            /* Scale down, saturate and store in output array */
+            *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+
+            res_Q6 = silk_SMULWB(         buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
+            res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
+
+            /* Scale down, saturate and store in output array */
+            *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+
+            buf_ptr += 3;
+            counter -= 3;
+        }
+
+        in += nSamplesIn;
+        inLen -= nSamplesIn;
+
+        if( inLen > 0 ) {
+            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+            silk_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
+        } else {
+            break;
+        }
+    }
+
+    /* Copy last part of filtered signal to the state for the next call */
+    silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private.h
new file mode 100644 (file)
index 0000000..1b7d353
--- /dev/null
@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_RESAMPLER_PRIVATE_H
+#define SILK_RESAMPLER_PRIVATE_H
+
+#include "SigProc_FIX.h"
+#include "resampler_structs.h"
+#include "resampler_rom.h"
+
+/* Number of input samples to process in the inner loop */
+#define RESAMPLER_MAX_BATCH_SIZE_MS             10
+#define RESAMPLER_MAX_FS_KHZ                    48
+#define RESAMPLER_MAX_BATCH_SIZE_IN             ( RESAMPLER_MAX_BATCH_SIZE_MS * RESAMPLER_MAX_FS_KHZ )
+
+/* Description: Hybrid IIR/FIR polyphase implementation of resampling */
+void silk_resampler_private_IIR_FIR(
+    void                            *SS,            /* I/O  Resampler state             */
+    opus_int16                      out[],          /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    opus_int32                      inLen           /* I    Number of input samples     */
+);
+
+/* Description: Hybrid IIR/FIR polyphase implementation of resampling */
+void silk_resampler_private_down_FIR(
+    void                            *SS,            /* I/O  Resampler state             */
+    opus_int16                      out[],          /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    opus_int32                      inLen           /* I    Number of input samples     */
+);
+
+/* Upsample by a factor 2, high quality */
+void silk_resampler_private_up2_HQ_wrapper(
+    void                            *SS,            /* I/O  Resampler state (unused)    */
+    opus_int16                      *out,           /* O    Output signal [ 2 * len ]   */
+    const opus_int16                *in,            /* I    Input signal [ len ]        */
+    opus_int32                      len             /* I    Number of input samples     */
+);
+
+/* Upsample by a factor 2, high quality */
+void silk_resampler_private_up2_HQ(
+    opus_int32                      *S,             /* I/O  Resampler state [ 6 ]       */
+    opus_int16                      *out,           /* O    Output signal [ 2 * len ]   */
+    const opus_int16                *in,            /* I    Input signal [ len ]        */
+    opus_int32                      len             /* I    Number of input samples     */
+);
+
+/* Second order AR filter */
+void silk_resampler_private_AR2(
+    opus_int32                      S[],            /* I/O  State vector [ 2 ]          */
+    opus_int32                      out_Q8[],       /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    const opus_int16                A_Q14[],        /* I    AR coefficients, Q14        */
+    opus_int32                      len             /* I    Signal length               */
+);
+
+#endif /* SILK_RESAMPLER_PRIVATE_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_AR2.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_AR2.c
new file mode 100644 (file)
index 0000000..73523d9
--- /dev/null
@@ -0,0 +1,54 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+
+/* Second order AR filter with single delay elements */
+void silk_resampler_private_AR2(
+    opus_int32                      S[],            /* I/O  State vector [ 2 ]          */
+    opus_int32                      out_Q8[],       /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    const opus_int16                A_Q14[],        /* I    AR coefficients, Q14        */
+    opus_int32                      len             /* I    Signal length               */
+)
+{
+    opus_int32    k;
+    opus_int32    out32;
+
+    for( k = 0; k < len; k++ ) {
+        out32       = silk_ADD_LSHIFT32( S[ 0 ], (opus_int32)in[ k ], 8 );
+        out_Q8[ k ] = out32;
+        out32       = silk_LSHIFT( out32, 2 );
+        S[ 0 ]      = silk_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] );
+        S[ 1 ]      = silk_SMULWB( out32, A_Q14[ 1 ] );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_IIR_FIR.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_IIR_FIR.c
new file mode 100644 (file)
index 0000000..6b2b3a2
--- /dev/null
@@ -0,0 +1,107 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+static OPUS_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL(
+    opus_int16  *out,
+    opus_int16  *buf,
+    opus_int32  max_index_Q16,
+    opus_int32  index_increment_Q16
+)
+{
+    opus_int32 index_Q16, res_Q15;
+    opus_int16 *buf_ptr;
+    opus_int32 table_index;
+
+    /* Interpolate upsampled signal and store in output array */
+    for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+        table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 );
+        buf_ptr = &buf[ index_Q16 >> 16 ];
+
+        res_Q15 = silk_SMULBB(          buf_ptr[ 0 ], silk_resampler_frac_FIR_12[      table_index ][ 0 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[      table_index ][ 1 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[      table_index ][ 2 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[      table_index ][ 3 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] );
+        *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) );
+    }
+    return out;
+}
+/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
+void silk_resampler_private_IIR_FIR(
+    void                            *SS,            /* I/O  Resampler state             */
+    opus_int16                      out[],          /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    opus_int32                      inLen           /* I    Number of input samples     */
+)
+{
+    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+    opus_int32 nSamplesIn;
+    opus_int32 max_index_Q16, index_increment_Q16;
+    VARDECL( opus_int16, buf );
+    SAVE_STACK;
+
+    ALLOC( buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, opus_int16 );
+
+    /* Copy buffered samples to start of buffer */
+    silk_memcpy( buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+
+    /* Iterate over blocks of frameSizeIn input samples */
+    index_increment_Q16 = S->invRatio_Q16;
+    while( 1 ) {
+        nSamplesIn = silk_min( inLen, S->batchSize );
+
+        /* Upsample 2x */
+        silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn );
+
+        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 );         /* + 1 because 2x upsampling */
+        out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 );
+        in += nSamplesIn;
+        inLen -= nSamplesIn;
+
+        if( inLen > 0 ) {
+            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+            silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+        } else {
+            break;
+        }
+    }
+
+    /* Copy last part of filtered signal to the state for the next call */
+    silk_memcpy( S->sFIR.i16, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_down_FIR.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_down_FIR.c
new file mode 100644 (file)
index 0000000..3e8735a
--- /dev/null
@@ -0,0 +1,194 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
+    opus_int16          *out,
+    opus_int32          *buf,
+    const opus_int16    *FIR_Coefs,
+    opus_int            FIR_Order,
+    opus_int            FIR_Fracs,
+    opus_int32          max_index_Q16,
+    opus_int32          index_increment_Q16
+)
+{
+    opus_int32 index_Q16, res_Q6;
+    opus_int32 *buf_ptr;
+    opus_int32 interpol_ind;
+    const opus_int16 *interpol_ptr;
+
+    switch( FIR_Order ) {
+        case RESAMPLER_DOWN_ORDER_FIR0:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Fractional part gives interpolation coefficients */
+                interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
+
+                /* Inner product */
+                interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ];
+                res_Q6 = silk_SMULWB(         buf_ptr[ 0 ], interpol_ptr[ 0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] );
+                interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[  9 ], interpol_ptr[ 8 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        case RESAMPLER_DOWN_ORDER_FIR1:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Inner product */
+                res_Q6 = silk_SMULWB(         silk_ADD32( buf_ptr[  0 ], buf_ptr[ 23 ] ), FIR_Coefs[  0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  1 ], buf_ptr[ 22 ] ), FIR_Coefs[  1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  2 ], buf_ptr[ 21 ] ), FIR_Coefs[  2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  3 ], buf_ptr[ 20 ] ), FIR_Coefs[  3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  4 ], buf_ptr[ 19 ] ), FIR_Coefs[  4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  5 ], buf_ptr[ 18 ] ), FIR_Coefs[  5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  6 ], buf_ptr[ 17 ] ), FIR_Coefs[  6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  7 ], buf_ptr[ 16 ] ), FIR_Coefs[  7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  8 ], buf_ptr[ 15 ] ), FIR_Coefs[  8 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  9 ], buf_ptr[ 14 ] ), FIR_Coefs[  9 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        case RESAMPLER_DOWN_ORDER_FIR2:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Inner product */
+                res_Q6 = silk_SMULWB(         silk_ADD32( buf_ptr[  0 ], buf_ptr[ 35 ] ), FIR_Coefs[  0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  1 ], buf_ptr[ 34 ] ), FIR_Coefs[  1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  2 ], buf_ptr[ 33 ] ), FIR_Coefs[  2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  3 ], buf_ptr[ 32 ] ), FIR_Coefs[  3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  4 ], buf_ptr[ 31 ] ), FIR_Coefs[  4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  5 ], buf_ptr[ 30 ] ), FIR_Coefs[  5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  6 ], buf_ptr[ 29 ] ), FIR_Coefs[  6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  7 ], buf_ptr[ 28 ] ), FIR_Coefs[  7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  8 ], buf_ptr[ 27 ] ), FIR_Coefs[  8 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  9 ], buf_ptr[ 26 ] ), FIR_Coefs[  9 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        default:
+            celt_assert( 0 );
+    }
+    return out;
+}
+
+/* Resample with a 2nd order AR filter followed by FIR interpolation */
+void silk_resampler_private_down_FIR(
+    void                            *SS,            /* I/O  Resampler state             */
+    opus_int16                      out[],          /* O    Output signal               */
+    const opus_int16                in[],           /* I    Input signal                */
+    opus_int32                      inLen           /* I    Number of input samples     */
+)
+{
+    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+    opus_int32 nSamplesIn;
+    opus_int32 max_index_Q16, index_increment_Q16;
+    VARDECL( opus_int32, buf );
+    const opus_int16 *FIR_Coefs;
+    SAVE_STACK;
+
+    ALLOC( buf, S->batchSize + S->FIR_Order, opus_int32 );
+
+    /* Copy buffered samples to start of buffer */
+    silk_memcpy( buf, S->sFIR.i32, S->FIR_Order * sizeof( opus_int32 ) );
+
+    FIR_Coefs = &S->Coefs[ 2 ];
+
+    /* Iterate over blocks of frameSizeIn input samples */
+    index_increment_Q16 = S->invRatio_Q16;
+    while( 1 ) {
+        nSamplesIn = silk_min( inLen, S->batchSize );
+
+        /* Second-order AR filter (output in Q8) */
+        silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn );
+
+        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
+
+        /* Interpolate filtered signal */
+        out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order,
+            S->FIR_Fracs, max_index_Q16, index_increment_Q16 );
+
+        in += nSamplesIn;
+        inLen -= nSamplesIn;
+
+        if( inLen > 1 ) {
+            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+            silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
+        } else {
+            break;
+        }
+    }
+
+    /* Copy last part of filtered signal to the state for the next call */
+    silk_memcpy( S->sFIR.i32, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
+    RESTORE_STACK;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_up2_HQ.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_private_up2_HQ.c
new file mode 100644 (file)
index 0000000..c7ec8de
--- /dev/null
@@ -0,0 +1,113 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+
+/* Upsample by a factor 2, high quality */
+/* Uses 2nd order allpass filters for the 2x upsampling, followed by a      */
+/* notch filter just above Nyquist.                                         */
+void silk_resampler_private_up2_HQ(
+    opus_int32                      *S,             /* I/O  Resampler state [ 6 ]       */
+    opus_int16                      *out,           /* O    Output signal [ 2 * len ]   */
+    const opus_int16                *in,            /* I    Input signal [ len ]        */
+    opus_int32                      len             /* I    Number of input samples     */
+)
+{
+    opus_int32 k;
+    opus_int32 in32, out32_1, out32_2, Y, X;
+
+    silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 );
+    silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 );
+
+    /* Internal variables and state are in Q10 format */
+    for( k = 0; k < len; k++ ) {
+        /* Convert to Q10 */
+        in32 = silk_LSHIFT( (opus_int32)in[ k ], 10 );
+
+        /* First all-pass section for even output sample */
+        Y       = silk_SUB32( in32, S[ 0 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] );
+        out32_1 = silk_ADD32( S[ 0 ], X );
+        S[ 0 ]  = silk_ADD32( in32, X );
+
+        /* Second all-pass section for even output sample */
+        Y       = silk_SUB32( out32_1, S[ 1 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] );
+        out32_2 = silk_ADD32( S[ 1 ], X );
+        S[ 1 ]  = silk_ADD32( out32_1, X );
+
+        /* Third all-pass section for even output sample */
+        Y       = silk_SUB32( out32_2, S[ 2 ] );
+        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] );
+        out32_1 = silk_ADD32( S[ 2 ], X );
+        S[ 2 ]  = silk_ADD32( out32_2, X );
+
+        /* Apply gain in Q15, convert back to int16 and store to output */
+        out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
+
+        /* First all-pass section for odd output sample */
+        Y       = silk_SUB32( in32, S[ 3 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] );
+        out32_1 = silk_ADD32( S[ 3 ], X );
+        S[ 3 ]  = silk_ADD32( in32, X );
+
+        /* Second all-pass section for odd output sample */
+        Y       = silk_SUB32( out32_1, S[ 4 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] );
+        out32_2 = silk_ADD32( S[ 4 ], X );
+        S[ 4 ]  = silk_ADD32( out32_1, X );
+
+        /* Third all-pass section for odd output sample */
+        Y       = silk_SUB32( out32_2, S[ 5 ] );
+        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] );
+        out32_1 = silk_ADD32( S[ 5 ], X );
+        S[ 5 ]  = silk_ADD32( out32_2, X );
+
+        /* Apply gain in Q15, convert back to int16 and store to output */
+        out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
+    }
+}
+
+void silk_resampler_private_up2_HQ_wrapper(
+    void                            *SS,            /* I/O  Resampler state (unused)    */
+    opus_int16                      *out,           /* O    Output signal [ 2 * len ]   */
+    const opus_int16                *in,            /* I    Input signal [ len ]        */
+    opus_int32                      len             /* I    Number of input samples     */
+)
+{
+    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+    silk_resampler_private_up2_HQ( S->sIIR, out, in, len );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.c
new file mode 100644 (file)
index 0000000..5e6b044
--- /dev/null
@@ -0,0 +1,96 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Filter coefficients for IIR/FIR polyphase resampling     *
+ * Total size: 179 Words (358 Bytes)                        */
+
+#include "resampler_private.h"
+
+/* Matlab code for the notch filter coefficients: */
+/* B = [1, 0.147, 1];  A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */
+/* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */
+/* const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634,  -7012,   7209,  30474 }; */
+
+/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+    -20694, -13867,
+       -49,     64,     17,   -157,    353,   -496,    163,  11047,  22205,
+       -39,      6,     91,   -170,    186,     23,   -896,   6336,  19928,
+       -19,    -36,    102,    -89,    -24,    328,   -951,   2568,  15909,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+    -14457, -14019,
+        64,    128,   -122,     36,    310,   -768,    584,   9267,  17733,
+        12,    128,     18,   -142,    288,   -117,   -865,   4123,  14459,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = {
+       616, -14323,
+       -10,     39,     58,    -46,    -84,    120,    184,   -315,   -541,   1284,   5380,   9024,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+     16102, -15162,
+       -13,      0,     20,     26,      5,    -31,    -43,     -4,     65,     90,      7,   -157,   -248,    -44,    593,   1583,   2612,   3271,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+     22500, -15099,
+         3,    -14,    -20,    -15,      2,     25,     37,     25,    -16,    -71,   -107,    -79,     50,    292,    623,    982,   1288,   1464,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+     27540, -15257,
+        17,     12,      8,      1,    -10,    -22,    -30,    -32,    -22,      3,     44,    100,    168,    243,    317,    381,    429,    455,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
+     -2797,  -6507,
+      4697,  10739,
+      1567,   8276,
+};
+
+/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = {
+    {  189,  -600,   617, 30567 },
+    {  117,  -159, -1070, 29704 },
+    {   52,   221, -2392, 28276 },
+    {   -4,   529, -3350, 26341 },
+    {  -48,   758, -3956, 23973 },
+    {  -80,   905, -4235, 21254 },
+    {  -99,   972, -4222, 18278 },
+    { -107,   967, -3957, 15143 },
+    { -103,   896, -3487, 11950 },
+    {  -91,   773, -2865,  8798 },
+    {  -71,   611, -2143,  5784 },
+    {  -46,   425, -1375,  2996 },
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_rom.h
new file mode 100644 (file)
index 0000000..b0579e0
--- /dev/null
@@ -0,0 +1,60 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_FIX_RESAMPLER_ROM_H
+#define SILK_FIX_RESAMPLER_ROM_H
+
+
+#include "typedef.h"
+#include "resampler_structs.h"
+
+#define RESAMPLER_DOWN_ORDER_FIR0               18
+#define RESAMPLER_DOWN_ORDER_FIR1               24
+#define RESAMPLER_DOWN_ORDER_FIR2               36
+#define RESAMPLER_ORDER_FIR_12                  8
+
+/* Tables for 2x downsampler */
+static const opus_int16 silk_resampler_down2_0 = 9872;
+static const opus_int16 silk_resampler_down2_1 = 39809 - 65536;
+
+/* Tables for 2x upsampler, high quality */
+static const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 };
+static const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 };
+
+/* Tables with IIR and FIR coefficients for fractional downsamplers */
+extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR1 / 2 ];
+extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_4_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_6_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ];
+
+/* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */
+extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ];
+
+#endif /* SILK_FIX_RESAMPLER_ROM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_structs.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/resampler_structs.h
new file mode 100644 (file)
index 0000000..80b426a
--- /dev/null
@@ -0,0 +1,52 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_RESAMPLER_STRUCTS_H
+#define SILK_RESAMPLER_STRUCTS_H
+
+#define SILK_RESAMPLER_MAX_FIR_ORDER                 36
+#define SILK_RESAMPLER_MAX_IIR_ORDER                 6
+
+typedef struct _silk_resampler_state_struct{
+    opus_int32       sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */
+    union{
+        opus_int32   i32[ SILK_RESAMPLER_MAX_FIR_ORDER ];
+        opus_int16   i16[ SILK_RESAMPLER_MAX_FIR_ORDER ];
+    }                sFIR;
+    opus_int16       delayBuf[ 96 ];
+    opus_int         resampler_function;
+    opus_int         batchSize;
+    opus_int32       invRatio_Q16;
+    opus_int         FIR_Order;
+    opus_int         FIR_Fracs;
+    opus_int         Fs_in_kHz;
+    opus_int         Fs_out_kHz;
+    opus_int         inputDelay;
+    const opus_int16 *Coefs;
+} silk_resampler_state_struct;
+
+#endif /* SILK_RESAMPLER_STRUCTS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/shell_coder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/shell_coder.c
new file mode 100644 (file)
index 0000000..4af3414
--- /dev/null
@@ -0,0 +1,151 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* shell coder; pulse-subframe length is hardcoded */
+
+static OPUS_INLINE void combine_pulses(
+    opus_int         *out,   /* O    combined pulses vector [len] */
+    const opus_int   *in,    /* I    input vector       [2 * len] */
+    const opus_int   len     /* I    number of OUTPUT samples     */
+)
+{
+    opus_int k;
+    for( k = 0; k < len; k++ ) {
+        out[ k ] = in[ 2 * k ] + in[ 2 * k + 1 ];
+    }
+}
+
+static OPUS_INLINE void encode_split(
+    ec_enc                      *psRangeEnc,    /* I/O  compressor data structure                   */
+    const opus_int              p_child1,       /* I    pulse amplitude of first child subframe     */
+    const opus_int              p,              /* I    pulse amplitude of current subframe         */
+    const opus_uint8            *shell_table    /* I    table of shell cdfs                         */
+)
+{
+    if( p > 0 ) {
+        ec_enc_icdf( psRangeEnc, p_child1, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 );
+    }
+}
+
+static OPUS_INLINE void decode_split(
+    opus_int16                  *p_child1,      /* O    pulse amplitude of first child subframe     */
+    opus_int16                  *p_child2,      /* O    pulse amplitude of second child subframe    */
+    ec_dec                      *psRangeDec,    /* I/O  Compressor data structure                   */
+    const opus_int              p,              /* I    pulse amplitude of current subframe         */
+    const opus_uint8            *shell_table    /* I    table of shell cdfs                         */
+)
+{
+    if( p > 0 ) {
+        p_child1[ 0 ] = ec_dec_icdf( psRangeDec, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 );
+        p_child2[ 0 ] = p - p_child1[ 0 ];
+    } else {
+        p_child1[ 0 ] = 0;
+        p_child2[ 0 ] = 0;
+    }
+}
+
+/* Shell encoder, operates on one shell code frame of 16 pulses */
+void silk_shell_encoder(
+    ec_enc                      *psRangeEnc,                    /* I/O  compressor data structure                   */
+    const opus_int              *pulses0                        /* I    data: nonnegative pulse amplitudes          */
+)
+{
+    opus_int pulses1[ 8 ], pulses2[ 4 ], pulses3[ 2 ], pulses4[ 1 ];
+
+    /* this function operates on one shell code frame of 16 pulses */
+    silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 );
+
+    /* tree representation per pulse-subframe */
+    combine_pulses( pulses1, pulses0, 8 );
+    combine_pulses( pulses2, pulses1, 4 );
+    combine_pulses( pulses3, pulses2, 2 );
+    combine_pulses( pulses4, pulses3, 1 );
+
+    encode_split( psRangeEnc, pulses3[  0 ], pulses4[ 0 ], silk_shell_code_table3 );
+
+    encode_split( psRangeEnc, pulses2[  0 ], pulses3[ 0 ], silk_shell_code_table2 );
+
+    encode_split( psRangeEnc, pulses1[  0 ], pulses2[ 0 ], silk_shell_code_table1 );
+    encode_split( psRangeEnc, pulses0[  0 ], pulses1[ 0 ], silk_shell_code_table0 );
+    encode_split( psRangeEnc, pulses0[  2 ], pulses1[ 1 ], silk_shell_code_table0 );
+
+    encode_split( psRangeEnc, pulses1[  2 ], pulses2[ 1 ], silk_shell_code_table1 );
+    encode_split( psRangeEnc, pulses0[  4 ], pulses1[ 2 ], silk_shell_code_table0 );
+    encode_split( psRangeEnc, pulses0[  6 ], pulses1[ 3 ], silk_shell_code_table0 );
+
+    encode_split( psRangeEnc, pulses2[  2 ], pulses3[ 1 ], silk_shell_code_table2 );
+
+    encode_split( psRangeEnc, pulses1[  4 ], pulses2[ 2 ], silk_shell_code_table1 );
+    encode_split( psRangeEnc, pulses0[  8 ], pulses1[ 4 ], silk_shell_code_table0 );
+    encode_split( psRangeEnc, pulses0[ 10 ], pulses1[ 5 ], silk_shell_code_table0 );
+
+    encode_split( psRangeEnc, pulses1[  6 ], pulses2[ 3 ], silk_shell_code_table1 );
+    encode_split( psRangeEnc, pulses0[ 12 ], pulses1[ 6 ], silk_shell_code_table0 );
+    encode_split( psRangeEnc, pulses0[ 14 ], pulses1[ 7 ], silk_shell_code_table0 );
+}
+
+
+/* Shell decoder, operates on one shell code frame of 16 pulses */
+void silk_shell_decoder(
+    opus_int16                  *pulses0,                       /* O    data: nonnegative pulse amplitudes          */
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    const opus_int              pulses4                         /* I    number of pulses per pulse-subframe         */
+)
+{
+    opus_int16 pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ];
+
+    /* this function operates on one shell code frame of 16 pulses */
+    silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 );
+
+    decode_split( &pulses3[  0 ], &pulses3[  1 ], psRangeDec, pulses4,      silk_shell_code_table3 );
+
+    decode_split( &pulses2[  0 ], &pulses2[  1 ], psRangeDec, pulses3[ 0 ], silk_shell_code_table2 );
+
+    decode_split( &pulses1[  0 ], &pulses1[  1 ], psRangeDec, pulses2[ 0 ], silk_shell_code_table1 );
+    decode_split( &pulses0[  0 ], &pulses0[  1 ], psRangeDec, pulses1[ 0 ], silk_shell_code_table0 );
+    decode_split( &pulses0[  2 ], &pulses0[  3 ], psRangeDec, pulses1[ 1 ], silk_shell_code_table0 );
+
+    decode_split( &pulses1[  2 ], &pulses1[  3 ], psRangeDec, pulses2[ 1 ], silk_shell_code_table1 );
+    decode_split( &pulses0[  4 ], &pulses0[  5 ], psRangeDec, pulses1[ 2 ], silk_shell_code_table0 );
+    decode_split( &pulses0[  6 ], &pulses0[  7 ], psRangeDec, pulses1[ 3 ], silk_shell_code_table0 );
+
+    decode_split( &pulses2[  2 ], &pulses2[  3 ], psRangeDec, pulses3[ 1 ], silk_shell_code_table2 );
+
+    decode_split( &pulses1[  4 ], &pulses1[  5 ], psRangeDec, pulses2[ 2 ], silk_shell_code_table1 );
+    decode_split( &pulses0[  8 ], &pulses0[  9 ], psRangeDec, pulses1[ 4 ], silk_shell_code_table0 );
+    decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], silk_shell_code_table0 );
+
+    decode_split( &pulses1[  6 ], &pulses1[  7 ], psRangeDec, pulses2[ 3 ], silk_shell_code_table1 );
+    decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], silk_shell_code_table0 );
+    decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], silk_shell_code_table0 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigm_Q15.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigm_Q15.c
new file mode 100644 (file)
index 0000000..39a52db
--- /dev/null
@@ -0,0 +1,75 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Approximate sigmoid function */
+
+#include "SigProc_FIX.h"
+
+/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */
+static const opus_int32 sigm_LUT_slope_Q10[ 6 ] = {
+    237, 153, 73, 30, 12, 7
+};
+/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */
+static const opus_int32 sigm_LUT_pos_Q15[ 6 ] = {
+    16384, 23955, 28861, 31213, 32178, 32548
+};
+/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */
+static const opus_int32 sigm_LUT_neg_Q15[ 6 ] = {
+    16384, 8812, 3906, 1554, 589, 219
+};
+
+opus_int silk_sigm_Q15(
+    opus_int                    in_Q5               /* I                                                                */
+)
+{
+    opus_int ind;
+
+    if( in_Q5 < 0 ) {
+        /* Negative input */
+        in_Q5 = -in_Q5;
+        if( in_Q5 >= 6 * 32 ) {
+            return 0;        /* Clip */
+        } else {
+            /* Linear interpolation of look up table */
+            ind = silk_RSHIFT( in_Q5, 5 );
+            return( sigm_LUT_neg_Q15[ ind ] - silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) );
+        }
+    } else {
+        /* Positive input */
+        if( in_Q5 >= 6 * 32 ) {
+            return 32767;        /* clip */
+        } else {
+            /* Linear interpolation of look up table */
+            ind = silk_RSHIFT( in_Q5, 5 );
+            return( sigm_LUT_pos_Q15[ ind ] + silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) );
+        }
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigproc_fix_mipsr1.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sigproc_fix_mipsr1.h
new file mode 100644 (file)
index 0000000..51520c0
--- /dev/null
@@ -0,0 +1,60 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_SIGPROC_FIX_MIPSR1_H
+#define SILK_SIGPROC_FIX_MIPSR1_H
+
+#undef silk_SAT16
+static inline short int silk_SAT16(int a)
+{
+    int c;
+    c = __builtin_mips_shll_s_w(a, 16);
+    c = c>>16;
+
+    return c;
+}
+
+#undef silk_LSHIFT_SAT32
+static inline int silk_LSHIFT_SAT32(int a, int shift)
+{
+    int r;
+
+    r = __builtin_mips_shll_s_w(a, shift);
+
+    return r;
+}
+
+#undef silk_RSHIFT_ROUND
+static inline int silk_RSHIFT_ROUND(int a, int shift)
+{
+    int r;
+
+    r = __builtin_mips_shra_r_w(a, shift);
+    return r;
+}
+
+#endif /* SILK_SIGPROC_FIX_MIPSR1_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sort.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sort.c
new file mode 100644 (file)
index 0000000..4fba16f
--- /dev/null
@@ -0,0 +1,154 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Insertion sort (fast for already almost sorted arrays):   */
+/* Best case:  O(n)   for an already sorted array            */
+/* Worst case: O(n^2) for an inversely sorted array          */
+/*                                                           */
+/* Shell short:    https://en.wikipedia.org/wiki/Shell_sort  */
+
+#include "SigProc_FIX.h"
+
+void silk_insertion_sort_increasing(
+    opus_int32           *a,             /* I/O   Unsorted / Sorted vector               */
+    opus_int             *idx,           /* O     Index vector for the sorted elements   */
+    const opus_int       L,              /* I     Vector length                          */
+    const opus_int       K               /* I     Number of correctly sorted positions   */
+)
+{
+    opus_int32    value;
+    opus_int        i, j;
+
+    /* Safety checks */
+    celt_assert( K >  0 );
+    celt_assert( L >  0 );
+    celt_assert( L >= K );
+
+    /* Write start indices in index vector */
+    for( i = 0; i < K; i++ ) {
+        idx[ i ] = i;
+    }
+
+    /* Sort vector elements by value, increasing order */
+    for( i = 1; i < K; i++ ) {
+        value = a[ i ];
+        for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+            a[ j + 1 ]   = a[ j ];       /* Shift value */
+            idx[ j + 1 ] = idx[ j ];     /* Shift index */
+        }
+        a[ j + 1 ]   = value;   /* Write value */
+        idx[ j + 1 ] = i;       /* Write index */
+    }
+
+    /* If less than L values are asked for, check the remaining values, */
+    /* but only spend CPU to ensure that the K first values are correct */
+    for( i = K; i < L; i++ ) {
+        value = a[ i ];
+        if( value < a[ K - 1 ] ) {
+            for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+                a[ j + 1 ]   = a[ j ];       /* Shift value */
+                idx[ j + 1 ] = idx[ j ];     /* Shift index */
+            }
+            a[ j + 1 ]   = value;   /* Write value */
+            idx[ j + 1 ] = i;       /* Write index */
+        }
+    }
+}
+
+#ifdef FIXED_POINT
+/* This function is only used by the fixed-point build */
+void silk_insertion_sort_decreasing_int16(
+    opus_int16                  *a,                 /* I/O   Unsorted / Sorted vector                                   */
+    opus_int                    *idx,               /* O     Index vector for the sorted elements                       */
+    const opus_int              L,                  /* I     Vector length                                              */
+    const opus_int              K                   /* I     Number of correctly sorted positions                       */
+)
+{
+    opus_int i, j;
+    opus_int value;
+
+    /* Safety checks */
+    celt_assert( K >  0 );
+    celt_assert( L >  0 );
+    celt_assert( L >= K );
+
+    /* Write start indices in index vector */
+    for( i = 0; i < K; i++ ) {
+        idx[ i ] = i;
+    }
+
+    /* Sort vector elements by value, decreasing order */
+    for( i = 1; i < K; i++ ) {
+        value = a[ i ];
+        for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+            a[ j + 1 ]   = a[ j ];     /* Shift value */
+            idx[ j + 1 ] = idx[ j ];   /* Shift index */
+        }
+        a[ j + 1 ]   = value;   /* Write value */
+        idx[ j + 1 ] = i;       /* Write index */
+    }
+
+    /* If less than L values are asked for, check the remaining values, */
+    /* but only spend CPU to ensure that the K first values are correct */
+    for( i = K; i < L; i++ ) {
+        value = a[ i ];
+        if( value > a[ K - 1 ] ) {
+            for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+                a[ j + 1 ]   = a[ j ];     /* Shift value */
+                idx[ j + 1 ] = idx[ j ];   /* Shift index */
+            }
+            a[ j + 1 ]   = value;   /* Write value */
+            idx[ j + 1 ] = i;       /* Write index */
+        }
+    }
+}
+#endif
+
+void silk_insertion_sort_increasing_all_values_int16(
+     opus_int16                 *a,                 /* I/O   Unsorted / Sorted vector                                   */
+     const opus_int             L                   /* I     Vector length                                              */
+)
+{
+    opus_int    value;
+    opus_int    i, j;
+
+    /* Safety checks */
+    celt_assert( L >  0 );
+
+    /* Sort vector elements by value, increasing order */
+    for( i = 1; i < L; i++ ) {
+        value = a[ i ];
+        for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+            a[ j + 1 ] = a[ j ]; /* Shift value */
+        }
+        a[ j + 1 ] = value; /* Write value */
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_MS_to_LR.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_MS_to_LR.c
new file mode 100644 (file)
index 0000000..1e01bb6
--- /dev/null
@@ -0,0 +1,85 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
+void silk_stereo_MS_to_LR(
+    stereo_dec_state            *state,                         /* I/O  State                                       */
+    opus_int16                  x1[],                           /* I/O  Left input signal, becomes mid signal       */
+    opus_int16                  x2[],                           /* I/O  Right input signal, becomes side signal     */
+    const opus_int32            pred_Q13[],                     /* I    Predictors                                  */
+    opus_int                    fs_kHz,                         /* I    Samples rate (kHz)                          */
+    opus_int                    frame_length                    /* I    Number of samples                           */
+)
+{
+    opus_int   n, denom_Q16, delta0_Q13, delta1_Q13;
+    opus_int32 sum, diff, pred0_Q13, pred1_Q13;
+
+    /* Buffering */
+    silk_memcpy( x1, state->sMid,  2 * sizeof( opus_int16 ) );
+    silk_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) );
+    silk_memcpy( state->sMid,  &x1[ frame_length ], 2 * sizeof( opus_int16 ) );
+    silk_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) );
+
+    /* Interpolate predictors and add prediction to side channel */
+    pred0_Q13  = state->pred_prev_Q13[ 0 ];
+    pred1_Q13  = state->pred_prev_Q13[ 1 ];
+    denom_Q16  = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz );
+    delta0_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 );
+    delta1_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 );
+    for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) {
+        pred0_Q13 += delta0_Q13;
+        pred1_Q13 += delta1_Q13;
+        sum = silk_LSHIFT( silk_ADD_LSHIFT32( x1[ n ] + (opus_int32)x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
+        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
+        x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
+    }
+    pred0_Q13 = pred_Q13[ 0 ];
+    pred1_Q13 = pred_Q13[ 1 ];
+    for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) {
+        sum = silk_LSHIFT( silk_ADD_LSHIFT32( x1[ n ] + (opus_int32)x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
+        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
+        x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
+    }
+    state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ];
+    state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ];
+
+    /* Convert to left/right signals */
+    for( n = 0; n < frame_length; n++ ) {
+        sum  = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ];
+        diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ];
+        x1[ n + 1 ] = (opus_int16)silk_SAT16( sum );
+        x2[ n + 1 ] = (opus_int16)silk_SAT16( diff );
+    }
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_decode_pred.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_decode_pred.c
new file mode 100644 (file)
index 0000000..56ba392
--- /dev/null
@@ -0,0 +1,73 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode mid/side predictors */
+void silk_stereo_decode_pred(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int32                  pred_Q13[]                      /* O    Predictors                                  */
+)
+{
+    opus_int   n, ix[ 2 ][ 3 ];
+    opus_int32 low_Q13, step_Q13;
+
+    /* Entropy decoding */
+    n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 );
+    ix[ 0 ][ 2 ] = silk_DIV32_16( n, 5 );
+    ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ];
+    for( n = 0; n < 2; n++ ) {
+        ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 );
+        ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 );
+    }
+
+    /* Dequantize */
+    for( n = 0; n < 2; n++ ) {
+        ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ];
+        low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ];
+        step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13,
+            SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) );
+        pred_Q13[ n ] = silk_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 );
+    }
+
+    /* Subtract second from first predictor (helps when actually applying these) */
+    pred_Q13[ 0 ] -= pred_Q13[ 1 ];
+}
+
+/* Decode mid-only flag */
+void silk_stereo_decode_mid_only(
+    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
+    opus_int                    *decode_only_mid                /* O    Flag that only mid channel has been coded   */
+)
+{
+    /* Decode flag that only mid channel is coded */
+    *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 );
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_find_predictor.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/stereo_find_predictor.c
new file mode 100644 (file)
index 0000000..e30e90b
--- /dev/null
@@ -0,0 +1,79 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Find least-squares prediction gain for one signal based on another and quantize it */
+opus_int32 silk_stereo_find_predictor(                          /* O    Returns predictor in Q13                    */
+    opus_int32                  *ratio_Q14,                     /* O    Ratio of residual and mid energies          */
+    const opus_int16            x[],                            /* I    Basis signal                                */
+    const opus_int16            y[],                            /* I    Target signal                               */
+    opus_int32                  mid_res_amp_Q0[],               /* I/O  Smoothed mid, residual norms                */
+    opus_int                    length,                         /* I    Number of samples                           */
+    opus_int                    smooth_coef_Q16                 /* I    Smoothing coefficient                       */
+)
+{
+    opus_int   scale, scale1, scale2;
+    opus_int32 nrgx, nrgy, corr, pred_Q13, pred2_Q10;
+
+    /* Find  predictor */
+    silk_sum_sqr_shift( &nrgx, &scale1, x, length );
+    silk_sum_sqr_shift( &nrgy, &scale2, y, length );
+    scale = silk_max_int( scale1, scale2 );
+    scale = scale + ( scale & 1 );          /* make even */
+    nrgy = silk_RSHIFT32( nrgy, scale - scale2 );
+    nrgx = silk_RSHIFT32( nrgx, scale - scale1 );
+    nrgx = silk_max_int( nrgx, 1 );
+    corr = silk_inner_prod_aligned_scale( x, y, scale, length );
+    pred_Q13 = silk_DIV32_varQ( corr, nrgx, 13 );
+    pred_Q13 = silk_LIMIT( pred_Q13, -(1 << 14), 1 << 14 );
+    pred2_Q10 = silk_SMULWB( pred_Q13, pred_Q13 );
+
+    /* Faster update for signals with large prediction parameters */
+    smooth_coef_Q16 = (opus_int)silk_max_int( smooth_coef_Q16, silk_abs( pred2_Q10 ) );
+
+    /* Smoothed mid and residual norms */
+    silk_assert( smooth_coef_Q16 < 32768 );
+    scale = silk_RSHIFT( scale, 1 );
+    mid_res_amp_Q0[ 0 ] = silk_SMLAWB( mid_res_amp_Q0[ 0 ], silk_LSHIFT( silk_SQRT_APPROX( nrgx ), scale ) - mid_res_amp_Q0[ 0 ],
+        smooth_coef_Q16 );
+    /* Residual energy = nrgy - 2 * pred * corr + pred^2 * nrgx */
+    nrgy = silk_SUB_LSHIFT32( nrgy, silk_SMULWB( corr, pred_Q13 ), 3 + 1 );
+    nrgy = silk_ADD_LSHIFT32( nrgy, silk_SMULWB( nrgx, pred2_Q10 ), 6 );
+    mid_res_amp_Q0[ 1 ] = silk_SMLAWB( mid_res_amp_Q0[ 1 ], silk_LSHIFT( silk_SQRT_APPROX( nrgy ), scale ) - mid_res_amp_Q0[ 1 ],
+        smooth_coef_Q16 );
+
+    /* Ratio of smoothed residual and mid norms */
+    *ratio_Q14 = silk_DIV32_varQ( mid_res_amp_Q0[ 1 ], silk_max( mid_res_amp_Q0[ 0 ], 1 ), 14 );
+    *ratio_Q14 = silk_LIMIT( *ratio_Q14, 0, 32767 );
+
+    return pred_Q13;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs.h
new file mode 100644 (file)
index 0000000..f3ea0b3
--- /dev/null
@@ -0,0 +1,357 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_STRUCTS_H
+#define SILK_STRUCTS_H
+
+#include "typedef.h"
+#include "SigProc_FIX.h"
+#include "define.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#include "lpcnet_private.h"
+#endif
+
+#ifdef ENABLE_DRED
+#include "dred_encoder.h"
+#include "dred_decoder.h"
+#endif
+
+#ifdef ENABLE_OSCE
+#include "osce_config.h"
+#include "osce_structs.h"
+#endif
+
+
+/************************************/
+/* Noise shaping quantization state */
+/************************************/
+typedef struct {
+    opus_int16                  xq[           2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal                             */
+    opus_int32                  sLTP_shp_Q14[ 2 * MAX_FRAME_LENGTH ];
+    opus_int32                  sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
+    opus_int32                  sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
+    opus_int32                  sLF_AR_shp_Q14;
+    opus_int32                  sDiff_shp_Q14;
+    opus_int                    lagPrev;
+    opus_int                    sLTP_buf_idx;
+    opus_int                    sLTP_shp_buf_idx;
+    opus_int32                  rand_seed;
+    opus_int32                  prev_gain_Q16;
+    opus_int                    rewhite_flag;
+} silk_nsq_state;
+
+/********************************/
+/* VAD state                    */
+/********************************/
+typedef struct {
+    opus_int32                  AnaState[ 2 ];                  /* Analysis filterbank state: 0-8 kHz                                   */
+    opus_int32                  AnaState1[ 2 ];                 /* Analysis filterbank state: 0-4 kHz                                   */
+    opus_int32                  AnaState2[ 2 ];                 /* Analysis filterbank state: 0-2 kHz                                   */
+    opus_int32                  XnrgSubfr[ VAD_N_BANDS ];       /* Subframe energies                                                    */
+    opus_int32                  NrgRatioSmth_Q8[ VAD_N_BANDS ]; /* Smoothed energy level in each band                                   */
+    opus_int16                  HPstate;                        /* State of differentiator in the lowest band                           */
+    opus_int32                  NL[ VAD_N_BANDS ];              /* Noise energy level in each band                                      */
+    opus_int32                  inv_NL[ VAD_N_BANDS ];          /* Inverse noise energy level in each band                              */
+    opus_int32                  NoiseLevelBias[ VAD_N_BANDS ];  /* Noise level estimator bias/offset                                    */
+    opus_int32                  counter;                        /* Frame counter used in the initial phase                              */
+} silk_VAD_state;
+
+/* Variable cut-off low-pass filter state */
+typedef struct {
+    opus_int32                   In_LP_State[ 2 ];           /* Low pass filter state */
+    opus_int32                   transition_frame_no;        /* Counter which is mapped to a cut-off frequency */
+    opus_int                     mode;                       /* Operating mode, <0: switch down, >0: switch up; 0: do nothing           */
+    opus_int32                   saved_fs_kHz;               /* If non-zero, holds the last sampling rate before a bandwidth switching reset. */
+} silk_LP_state;
+
+/* Structure containing NLSF codebook */
+typedef struct {
+    const opus_int16             nVectors;
+    const opus_int16             order;
+    const opus_int16             quantStepSize_Q16;
+    const opus_int16             invQuantStepSize_Q6;
+    const opus_uint8             *CB1_NLSF_Q8;
+    const opus_int16             *CB1_Wght_Q9;
+    const opus_uint8             *CB1_iCDF;
+    const opus_uint8             *pred_Q8;
+    const opus_uint8             *ec_sel;
+    const opus_uint8             *ec_iCDF;
+    const opus_uint8             *ec_Rates_Q5;
+    const opus_int16             *deltaMin_Q15;
+} silk_NLSF_CB_struct;
+
+typedef struct {
+    opus_int16                   pred_prev_Q13[ 2 ];
+    opus_int16                   sMid[ 2 ];
+    opus_int16                   sSide[ 2 ];
+    opus_int32                   mid_side_amp_Q0[ 4 ];
+    opus_int16                   smth_width_Q14;
+    opus_int16                   width_prev_Q14;
+    opus_int16                   silent_side_len;
+    opus_int8                    predIx[ MAX_FRAMES_PER_PACKET ][ 2 ][ 3 ];
+    opus_int8                    mid_only_flags[ MAX_FRAMES_PER_PACKET ];
+} stereo_enc_state;
+
+typedef struct {
+    opus_int16                   pred_prev_Q13[ 2 ];
+    opus_int16                   sMid[ 2 ];
+    opus_int16                   sSide[ 2 ];
+} stereo_dec_state;
+
+typedef struct {
+    opus_int8                    GainsIndices[ MAX_NB_SUBFR ];
+    opus_int8                    LTPIndex[ MAX_NB_SUBFR ];
+    opus_int8                    NLSFIndices[ MAX_LPC_ORDER + 1 ];
+    opus_int16                   lagIndex;
+    opus_int8                    contourIndex;
+    opus_int8                    signalType;
+    opus_int8                    quantOffsetType;
+    opus_int8                    NLSFInterpCoef_Q2;
+    opus_int8                    PERIndex;
+    opus_int8                    LTP_scaleIndex;
+    opus_int8                    Seed;
+} SideInfoIndices;
+
+/********************************/
+/* Encoder state                */
+/********************************/
+typedef struct {
+    opus_int32                   In_HP_State[ 2 ];                  /* High pass filter state                                           */
+    opus_int32                   variable_HP_smth1_Q15;             /* State of first smoother                                          */
+    opus_int32                   variable_HP_smth2_Q15;             /* State of second smoother                                         */
+    silk_LP_state                sLP;                               /* Low pass filter state                                            */
+    silk_VAD_state               sVAD;                              /* Voice activity detector state                                    */
+    silk_nsq_state               sNSQ;                              /* Noise Shape Quantizer State                                      */
+    opus_int16                   prev_NLSFq_Q15[ MAX_LPC_ORDER ];   /* Previously quantized NLSF vector                                 */
+    opus_int                     speech_activity_Q8;                /* Speech activity                                                  */
+    opus_int                     allow_bandwidth_switch;            /* Flag indicating that switching of internal bandwidth is allowed  */
+    opus_int8                    LBRRprevLastGainIndex;
+    opus_int8                    prevSignalType;
+    opus_int                     prevLag;
+    opus_int                     pitch_LPC_win_length;
+    opus_int                     max_pitch_lag;                     /* Highest possible pitch lag (samples)                             */
+    opus_int32                   API_fs_Hz;                         /* API sampling frequency (Hz)                                      */
+    opus_int32                   prev_API_fs_Hz;                    /* Previous API sampling frequency (Hz)                             */
+    opus_int                     maxInternal_fs_Hz;                 /* Maximum internal sampling frequency (Hz)                         */
+    opus_int                     minInternal_fs_Hz;                 /* Minimum internal sampling frequency (Hz)                         */
+    opus_int                     desiredInternal_fs_Hz;             /* Soft request for internal sampling frequency (Hz)                */
+    opus_int                     fs_kHz;                            /* Internal sampling frequency (kHz)                                */
+    opus_int                     nb_subfr;                          /* Number of 5 ms subframes in a frame                              */
+    opus_int                     frame_length;                      /* Frame length (samples)                                           */
+    opus_int                     subfr_length;                      /* Subframe length (samples)                                        */
+    opus_int                     ltp_mem_length;                    /* Length of LTP memory                                             */
+    opus_int                     la_pitch;                          /* Look-ahead for pitch analysis (samples)                          */
+    opus_int                     la_shape;                          /* Look-ahead for noise shape analysis (samples)                    */
+    opus_int                     shapeWinLength;                    /* Window length for noise shape analysis (samples)                 */
+    opus_int32                   TargetRate_bps;                    /* Target bitrate (bps)                                             */
+    opus_int                     PacketSize_ms;                     /* Number of milliseconds to put in each packet                     */
+    opus_int                     PacketLoss_perc;                   /* Packet loss rate measured by farend                              */
+    opus_int32                   frameCounter;
+    opus_int                     Complexity;                        /* Complexity setting                                               */
+    opus_int                     nStatesDelayedDecision;            /* Number of states in delayed decision quantization                */
+    opus_int                     useInterpolatedNLSFs;              /* Flag for using NLSF interpolation                                */
+    opus_int                     shapingLPCOrder;                   /* Filter order for noise shaping filters                           */
+    opus_int                     predictLPCOrder;                   /* Filter order for prediction filters                              */
+    opus_int                     pitchEstimationComplexity;         /* Complexity level for pitch estimator                             */
+    opus_int                     pitchEstimationLPCOrder;           /* Whitening filter order for pitch estimator                       */
+    opus_int32                   pitchEstimationThreshold_Q16;      /* Threshold for pitch estimator                                    */
+    opus_int32                   sum_log_gain_Q7;                   /* Cumulative max prediction gain                                   */
+    opus_int                     NLSF_MSVQ_Survivors;               /* Number of survivors in NLSF MSVQ                                 */
+    opus_int                     first_frame_after_reset;           /* Flag for deactivating NLSF interpolation, pitch prediction       */
+    opus_int                     controlled_since_last_payload;     /* Flag for ensuring codec_control only runs once per packet        */
+    opus_int                     warping_Q16;                       /* Warping parameter for warped noise shaping                       */
+    opus_int                     useCBR;                            /* Flag to enable constant bitrate                                  */
+    opus_int                     prefillFlag;                       /* Flag to indicate that only buffers are prefilled, no coding      */
+    const opus_uint8             *pitch_lag_low_bits_iCDF;          /* Pointer to iCDF table for low bits of pitch lag index            */
+    const opus_uint8             *pitch_contour_iCDF;               /* Pointer to iCDF table for pitch contour index                    */
+    const silk_NLSF_CB_struct    *psNLSF_CB;                        /* Pointer to NLSF codebook                                         */
+    opus_int                     input_quality_bands_Q15[ VAD_N_BANDS ];
+    opus_int                     input_tilt_Q15;
+    opus_int                     SNR_dB_Q7;                         /* Quality setting                                                  */
+
+    opus_int8                    VAD_flags[ MAX_FRAMES_PER_PACKET ];
+    opus_int8                    LBRR_flag;
+    opus_int                     LBRR_flags[ MAX_FRAMES_PER_PACKET ];
+
+    SideInfoIndices              indices;
+    opus_int8                    pulses[ MAX_FRAME_LENGTH ];
+
+    int                          arch;
+
+    /* Input/output buffering */
+    opus_int16                   inputBuf[ MAX_FRAME_LENGTH + 2 ];  /* Buffer containing input signal                                   */
+    opus_int                     inputBufIx;
+    opus_int                     nFramesPerPacket;
+    opus_int                     nFramesEncoded;                    /* Number of frames analyzed in current packet                      */
+
+    opus_int                     nChannelsAPI;
+    opus_int                     nChannelsInternal;
+    opus_int                     channelNb;
+
+    /* Parameters For LTP scaling Control */
+    opus_int                     frames_since_onset;
+
+    /* Specifically for entropy coding */
+    opus_int                     ec_prevSignalType;
+    opus_int16                   ec_prevLagIndex;
+
+    silk_resampler_state_struct resampler_state;
+
+    /* DTX */
+    opus_int                     useDTX;                            /* Flag to enable DTX                                               */
+    opus_int                     inDTX;                             /* Flag to signal DTX period                                        */
+    opus_int                     noSpeechCounter;                   /* Counts concecutive nonactive frames, used by DTX                 */
+
+    /* Inband Low Bitrate Redundancy (LBRR) data */
+    opus_int                     useInBandFEC;                      /* Saves the API setting for query                                  */
+    opus_int                     LBRR_enabled;                      /* Depends on useInBandFRC, bitrate and packet loss rate            */
+    opus_int                     LBRR_GainIncreases;                /* Gains increment for coding LBRR frames                           */
+    SideInfoIndices              indices_LBRR[ MAX_FRAMES_PER_PACKET ];
+    opus_int8                    pulses_LBRR[ MAX_FRAMES_PER_PACKET ][ MAX_FRAME_LENGTH ];
+} silk_encoder_state;
+
+
+#ifdef ENABLE_OSCE
+typedef struct {
+    OSCEFeatureState features;
+    OSCEState state;
+    int method;
+} silk_OSCE_struct;
+
+typedef struct {
+    OSCEBWEFeatureState features;
+    OSCEBWEState state;
+} silk_OSCE_BWE_struct;
+#endif
+
+/* Struct for Packet Loss Concealment */
+typedef struct {
+    opus_int32                  pitchL_Q8;                          /* Pitch lag to use for voiced concealment                          */
+    opus_int16                  LTPCoef_Q14[ LTP_ORDER ];           /* LTP coefficients to use for voiced concealment                   */
+    opus_int16                  prevLPC_Q12[ MAX_LPC_ORDER ];
+    opus_int                    last_frame_lost;                    /* Was previous frame lost                                          */
+    opus_int32                  rand_seed;                          /* Seed for unvoiced signal generation                              */
+    opus_int16                  randScale_Q14;                      /* Scaling of unvoiced random signal                                */
+    opus_int32                  conc_energy;
+    opus_int                    conc_energy_shift;
+    opus_int16                  prevLTP_scale_Q14;
+    opus_int32                  prevGain_Q16[ 2 ];
+    opus_int                    fs_kHz;
+    opus_int                    nb_subfr;
+    opus_int                    subfr_length;
+    opus_int                    enable_deep_plc;
+} silk_PLC_struct;
+
+/* Struct for CNG */
+typedef struct {
+    opus_int32                  CNG_exc_buf_Q14[ MAX_FRAME_LENGTH ];
+    opus_int16                  CNG_smth_NLSF_Q15[ MAX_LPC_ORDER ];
+    opus_int32                  CNG_synth_state[ MAX_LPC_ORDER ];
+    opus_int32                  CNG_smth_Gain_Q16;
+    opus_int32                  rand_seed;
+    opus_int                    fs_kHz;
+} silk_CNG_struct;
+
+/********************************/
+/* Decoder state                */
+/********************************/
+typedef struct {
+#ifdef ENABLE_OSCE
+    silk_OSCE_struct            osce;
+#ifdef ENABLE_OSCE_BWE
+    silk_OSCE_BWE_struct        osce_bwe;
+#endif
+#endif
+#define SILK_DECODER_STATE_RESET_START prev_gain_Q16
+    opus_int32                  prev_gain_Q16;
+    opus_int32                  exc_Q14[ MAX_FRAME_LENGTH ];
+    opus_int32                  sLPC_Q14_buf[ MAX_LPC_ORDER ];
+    opus_int16                  outBuf[ MAX_FRAME_LENGTH + 2 * MAX_SUB_FRAME_LENGTH ];  /* Buffer for output signal                     */
+    opus_int                    lagPrev;                            /* Previous Lag                                                     */
+    opus_int8                   LastGainIndex;                      /* Previous gain index                                              */
+    opus_int                    fs_kHz;                             /* Sampling frequency in kHz                                        */
+    opus_int32                  fs_API_hz;                          /* API sample frequency (Hz)                                        */
+    opus_int                    nb_subfr;                           /* Number of 5 ms subframes in a frame                              */
+    opus_int                    frame_length;                       /* Frame length (samples)                                           */
+    opus_int                    subfr_length;                       /* Subframe length (samples)                                        */
+    opus_int                    ltp_mem_length;                     /* Length of LTP memory                                             */
+    opus_int                    LPC_order;                          /* LPC order                                                        */
+    opus_int16                  prevNLSF_Q15[ MAX_LPC_ORDER ];      /* Used to interpolate LSFs                                         */
+    opus_int                    first_frame_after_reset;            /* Flag for deactivating NLSF interpolation                         */
+    const opus_uint8            *pitch_lag_low_bits_iCDF;           /* Pointer to iCDF table for low bits of pitch lag index            */
+    const opus_uint8            *pitch_contour_iCDF;                /* Pointer to iCDF table for pitch contour index                    */
+
+    /* For buffering payload in case of more frames per packet */
+    opus_int                    nFramesDecoded;
+    opus_int                    nFramesPerPacket;
+
+    /* Specifically for entropy coding */
+    opus_int                    ec_prevSignalType;
+    opus_int16                  ec_prevLagIndex;
+
+    opus_int                    VAD_flags[ MAX_FRAMES_PER_PACKET ];
+    opus_int                    LBRR_flag;
+    opus_int                    LBRR_flags[ MAX_FRAMES_PER_PACKET ];
+
+    silk_resampler_state_struct resampler_state;
+
+    const silk_NLSF_CB_struct   *psNLSF_CB;                         /* Pointer to NLSF codebook                                         */
+
+    /* Quantization indices */
+    SideInfoIndices             indices;
+
+    /* CNG state */
+    silk_CNG_struct             sCNG;
+
+    /* Stuff used for PLC */
+    opus_int                    lossCnt;
+    opus_int                    prevSignalType;
+    int                         arch;
+
+    silk_PLC_struct sPLC;
+
+} silk_decoder_state;
+
+/************************/
+/* Decoder control      */
+/************************/
+typedef struct {
+    /* Prediction and coding parameters */
+    opus_int                    pitchL[ MAX_NB_SUBFR ];
+    opus_int32                  Gains_Q16[ MAX_NB_SUBFR ];
+    /* Holds interpolated and final coefficients, 4-byte aligned */
+    silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+    opus_int16                  LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+    opus_int                    LTP_scale_Q14;
+} silk_decoder_control;
+
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FIX.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FIX.h
new file mode 100644 (file)
index 0000000..42920d6
--- /dev/null
@@ -0,0 +1,109 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_STRUCTS_FIX_H
+#define SILK_STRUCTS_FIX_H
+
+#include "typedef.h"
+#include "main.h"
+#include "structs.h"
+
+
+/********************************/
+/* Noise shaping analysis state */
+/********************************/
+typedef struct {
+    opus_int8                   LastGainIndex;
+    opus_int32                  HarmBoost_smth_Q16;
+    opus_int32                  HarmShapeGain_smth_Q16;
+    opus_int32                  Tilt_smth_Q16;
+} silk_shape_state_FIX;
+
+/********************************/
+/* Encoder state FIX            */
+/********************************/
+typedef struct {
+    silk_encoder_state          sCmn;                                   /* Common struct, shared with floating-point code       */
+    silk_shape_state_FIX        sShape;                                 /* Shape state                                          */
+
+    /* Buffer for find pitch and noise shape analysis */
+    silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis  */
+    opus_int                    LTPCorr_Q15;                            /* Normalized correlation from pitch lag estimator      */
+    opus_int32                    resNrgSmth;
+} silk_encoder_state_FIX;
+
+/************************/
+/* Encoder control FIX  */
+/************************/
+typedef struct {
+    /* Prediction and coding parameters */
+    opus_int32                  Gains_Q16[ MAX_NB_SUBFR ];
+    silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+    opus_int16                  LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+    opus_int                    LTP_scale_Q14;
+    opus_int                    pitchL[ MAX_NB_SUBFR ];
+
+    /* Noise shaping parameters */
+    /* Testing */
+    silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    opus_int32                  LF_shp_Q14[        MAX_NB_SUBFR ];      /* Packs two int16 coefficients per int32 value         */
+    opus_int                    Tilt_Q14[          MAX_NB_SUBFR ];
+    opus_int                    HarmShapeGain_Q14[ MAX_NB_SUBFR ];
+    opus_int                    Lambda_Q10;
+    opus_int                    input_quality_Q14;
+    opus_int                    coding_quality_Q14;
+
+    /* measures */
+    opus_int32                  predGain_Q16;
+    opus_int                    LTPredCodGain_Q7;
+    opus_int32                  ResNrg[ MAX_NB_SUBFR ];                 /* Residual energy per subframe                         */
+    opus_int                    ResNrgQ[ MAX_NB_SUBFR ];                /* Q domain for the residual energy > 0                 */
+
+    /* Parameters for CBR mode */
+    opus_int32                  GainsUnq_Q16[ MAX_NB_SUBFR ];
+    opus_int8                   lastGainIndexPrev;
+} silk_encoder_control_FIX;
+
+/************************/
+/* Encoder Super Struct */
+/************************/
+typedef struct {
+    stereo_enc_state            sStereo;
+    opus_int32                  nBitsUsedLBRR;
+    opus_int32                  nBitsExceeded;
+    opus_int                    nChannelsAPI;
+    opus_int                    nChannelsInternal;
+    opus_int                    nPrevChannelsInternal;
+    opus_int                    timeSinceSwitchAllowed_ms;
+    opus_int                    allowBandwidthSwitch;
+    opus_int                    prev_decode_only_middle;
+    /* This needs to be last so we can skip the second state for mono. */
+    silk_encoder_state_FIX      state_Fxx[ ENCODER_NUM_CHANNELS ];
+} silk_encoder;
+
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FLP.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/structs_FLP.h
new file mode 100644 (file)
index 0000000..8eac15c
--- /dev/null
@@ -0,0 +1,105 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_STRUCTS_FLP_H
+#define SILK_STRUCTS_FLP_H
+
+#include "typedef.h"
+#include "main.h"
+#include "structs.h"
+
+
+/********************************/
+/* Noise shaping analysis state */
+/********************************/
+typedef struct {
+    opus_int8                   LastGainIndex;
+    silk_float                  HarmShapeGain_smth;
+    silk_float                  Tilt_smth;
+} silk_shape_state_FLP;
+
+/********************************/
+/* Encoder state FLP            */
+/********************************/
+typedef struct {
+    silk_encoder_state          sCmn;                               /* Common struct, shared with fixed-point code */
+    silk_shape_state_FLP        sShape;                             /* Noise shaping state */
+
+    /* Buffer for find pitch and noise shape analysis */
+    silk_float                  x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
+    silk_float                  LTPCorr;                            /* Normalized correlation from pitch lag estimator */
+} silk_encoder_state_FLP;
+
+/************************/
+/* Encoder control FLP  */
+/************************/
+typedef struct {
+    /* Prediction and coding parameters */
+    silk_float                  Gains[ MAX_NB_SUBFR ];
+    silk_float                  PredCoef[ 2 ][ MAX_LPC_ORDER ];     /* holds interpolated and final coefficients */
+    silk_float                  LTPCoef[LTP_ORDER * MAX_NB_SUBFR];
+    silk_float                  LTP_scale;
+    opus_int                    pitchL[ MAX_NB_SUBFR ];
+
+    /* Noise shaping parameters */
+    silk_float                  AR[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    silk_float                  LF_MA_shp[     MAX_NB_SUBFR ];
+    silk_float                  LF_AR_shp[     MAX_NB_SUBFR ];
+    silk_float                  Tilt[          MAX_NB_SUBFR ];
+    silk_float                  HarmShapeGain[ MAX_NB_SUBFR ];
+    silk_float                  Lambda;
+    silk_float                  input_quality;
+    silk_float                  coding_quality;
+
+    /* Measures */
+    silk_float                  predGain;
+    silk_float                  LTPredCodGain;
+    silk_float                  ResNrg[ MAX_NB_SUBFR ];             /* Residual energy per subframe */
+
+    /* Parameters for CBR mode */
+    opus_int32                  GainsUnq_Q16[ MAX_NB_SUBFR ];
+    opus_int8                   lastGainIndexPrev;
+} silk_encoder_control_FLP;
+
+/************************/
+/* Encoder Super Struct */
+/************************/
+typedef struct {
+    stereo_enc_state            sStereo;
+    opus_int32                  nBitsUsedLBRR;
+    opus_int32                  nBitsExceeded;
+    opus_int                    nChannelsAPI;
+    opus_int                    nChannelsInternal;
+    opus_int                    nPrevChannelsInternal;
+    opus_int                    timeSinceSwitchAllowed_ms;
+    opus_int                    allowBandwidthSwitch;
+    opus_int                    prev_decode_only_middle;
+    /* This needs to be last so we can skip the second state for mono. */
+    silk_encoder_state_FLP      state_Fxx[ ENCODER_NUM_CHANNELS ];
+} silk_encoder;
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sum_sqr_shift.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/sum_sqr_shift.c
new file mode 100644 (file)
index 0000000..90ceb76
--- /dev/null
@@ -0,0 +1,82 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Compute number of bits to right shift the sum of squares of a vector */
+/* of int16s to make it fit in an int32                                 */
+void silk_sum_sqr_shift(
+    opus_int32                  *energy,            /* O   Energy of x, after shifting to the right                     */
+    opus_int                    *shift,             /* O   Number of bits right shift applied to energy                 */
+    const opus_int16            *x,                 /* I   Input vector                                                 */
+    opus_int                    len                 /* I   Length of input vector                                       */
+)
+{
+    opus_int   i, shft;
+    opus_uint32 nrg_tmp;
+    opus_int32 nrg;
+
+    /* Do a first run with the maximum shift we could have. */
+    shft = 31-silk_CLZ32(len);
+    /* Let's be conservative with rounding and start with nrg=len. */
+    nrg  = len;
+    for( i = 0; i < len - 1; i += 2 ) {
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+    if( i < len ) {
+        /* One sample left to process */
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+    silk_assert( nrg >= 0 );
+    /* Make sure the result will fit in a 32-bit signed integer with two bits
+       of headroom. */
+    shft = silk_max_32(0, shft+3 - silk_CLZ32(nrg));
+    nrg = 0;
+    for( i = 0 ; i < len - 1; i += 2 ) {
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+    if( i < len ) {
+        /* One sample left to process */
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+
+    silk_assert( nrg >= 0 );
+
+    /* Output arguments */
+    *shift  = shft;
+    *energy = nrg;
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/table_LSF_cos.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/table_LSF_cos.c
new file mode 100644 (file)
index 0000000..ec9dc63
--- /dev/null
@@ -0,0 +1,70 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+/* Cosine approximation table for LSF conversion */
+/* Q12 values (even) */
+const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ] = {
+            8192,             8190,             8182,             8170,
+            8152,             8130,             8104,             8072,
+            8034,             7994,             7946,             7896,
+            7840,             7778,             7714,             7644,
+            7568,             7490,             7406,             7318,
+            7226,             7128,             7026,             6922,
+            6812,             6698,             6580,             6458,
+            6332,             6204,             6070,             5934,
+            5792,             5648,             5502,             5352,
+            5198,             5040,             4880,             4718,
+            4552,             4382,             4212,             4038,
+            3862,             3684,             3502,             3320,
+            3136,             2948,             2760,             2570,
+            2378,             2186,             1990,             1794,
+            1598,             1400,             1202,             1002,
+             802,              602,              402,              202,
+               0,             -202,             -402,             -602,
+            -802,            -1002,            -1202,            -1400,
+           -1598,            -1794,            -1990,            -2186,
+           -2378,            -2570,            -2760,            -2948,
+           -3136,            -3320,            -3502,            -3684,
+           -3862,            -4038,            -4212,            -4382,
+           -4552,            -4718,            -4880,            -5040,
+           -5198,            -5352,            -5502,            -5648,
+           -5792,            -5934,            -6070,            -6204,
+           -6332,            -6458,            -6580,            -6698,
+           -6812,            -6922,            -7026,            -7128,
+           -7226,            -7318,            -7406,            -7490,
+           -7568,            -7644,            -7714,            -7778,
+           -7840,            -7896,            -7946,            -7994,
+           -8034,            -8072,            -8104,            -8130,
+           -8152,            -8170,            -8182,            -8190,
+           -8192
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables.h
new file mode 100644 (file)
index 0000000..da12b66
--- /dev/null
@@ -0,0 +1,106 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_TABLES_H
+#define SILK_TABLES_H
+
+#include "define.h"
+#include "structs.h"
+
+
+/* Entropy coding tables (with size in bytes indicated) */
+extern const opus_uint8  silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ];                                 /* 24 */
+extern const opus_uint8  silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ];   /* 41 */
+
+extern const opus_uint8  silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ];/* 32 */
+extern const opus_uint8  silk_pitch_delta_iCDF[ 21 ];                                               /*  21 */
+extern const opus_uint8  silk_pitch_contour_iCDF[ 34 ];                                             /*  34 */
+extern const opus_uint8  silk_pitch_contour_NB_iCDF[ 11 ];                                          /*  11 */
+extern const opus_uint8  silk_pitch_contour_10_ms_iCDF[ 12 ];                                       /*  12 */
+extern const opus_uint8  silk_pitch_contour_10_ms_NB_iCDF[ 3 ];                                     /*   3 */
+
+extern const opus_uint8  silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ SILK_MAX_PULSES + 2 ];        /* 180 */
+extern const opus_uint8  silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ SILK_MAX_PULSES + 2 ]; /* 162 */
+
+extern const opus_uint8  silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ];                           /*  18 */
+extern const opus_uint8  silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ];                        /*  18 */
+
+extern const opus_uint8  silk_max_pulses_table[ 4 ];                                                /*   4 */
+
+extern const opus_uint8  silk_shell_code_table0[ 152 ];                                             /* 152 */
+extern const opus_uint8  silk_shell_code_table1[ 152 ];                                             /* 152 */
+extern const opus_uint8  silk_shell_code_table2[ 152 ];                                             /* 152 */
+extern const opus_uint8  silk_shell_code_table3[ 152 ];                                             /* 152 */
+extern const opus_uint8  silk_shell_code_table_offsets[ SILK_MAX_PULSES + 1 ];                      /*  17 */
+
+extern const opus_uint8  silk_lsb_iCDF[ 2 ];                                                        /*   2 */
+
+extern const opus_uint8  silk_sign_iCDF[ 42 ];                                                      /*  42 */
+
+extern const opus_uint8  silk_uniform3_iCDF[ 3 ];                                                   /*   3 */
+extern const opus_uint8  silk_uniform4_iCDF[ 4 ];                                                   /*   4 */
+extern const opus_uint8  silk_uniform5_iCDF[ 5 ];                                                   /*   5 */
+extern const opus_uint8  silk_uniform6_iCDF[ 6 ];                                                   /*   6 */
+extern const opus_uint8  silk_uniform8_iCDF[ 8 ];                                                   /*   8 */
+
+extern const opus_uint8  silk_NLSF_EXT_iCDF[ 7 ];                                                   /*   7 */
+
+extern const opus_uint8  silk_LTP_per_index_iCDF[ 3 ];                                              /*   3 */
+extern const opus_uint8  * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ];                            /*   3 */
+extern const opus_uint8  * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ];                         /*   3 */
+extern const opus_int8   * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ];                                /* 168 */
+extern const opus_uint8  * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS];
+extern const opus_int8   silk_LTP_vq_sizes[ NB_LTP_CBKS ];                                          /*   3 */
+
+extern const opus_uint8  silk_LTPscale_iCDF[ 3 ];                                                   /*   4 */
+extern const opus_int16  silk_LTPScales_table_Q14[ 3 ];                                             /*   6 */
+
+extern const opus_uint8  silk_type_offset_VAD_iCDF[ 4 ];                                            /*   4 */
+extern const opus_uint8  silk_type_offset_no_VAD_iCDF[ 2 ];                                         /*   2 */
+
+extern const opus_int16  silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ];                       /*  32 */
+extern const opus_uint8  silk_stereo_pred_joint_iCDF[ 25 ];                                         /*  25 */
+extern const opus_uint8  silk_stereo_only_code_mid_iCDF[ 2 ];                                       /*   2 */
+
+extern const opus_uint8  * const silk_LBRR_flags_iCDF_ptr[ 2 ];                                     /*  10 */
+
+extern const opus_uint8  silk_NLSF_interpolation_factor_iCDF[ 5 ];                                  /*   5 */
+
+extern const silk_NLSF_CB_struct silk_NLSF_CB_WB;                                                   /* 1040 */
+extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB;                                                /* 728 */
+
+/* Quantization offsets */
+extern const opus_int16  silk_Quantization_Offsets_Q10[ 2 ][ 2 ];                                   /*   8 */
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+extern const opus_int32  silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ];           /*  60 */
+extern const opus_int32  silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ];           /*  60 */
+
+/* Rom table with cosine values */
+extern const opus_int16  silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ];                          /* 258 */
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_LTP.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_LTP.c
new file mode 100644 (file)
index 0000000..5e12c86
--- /dev/null
@@ -0,0 +1,294 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_LTP_per_index_iCDF[3] = {
+       179,     99,      0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_0[8] = {
+        71,     56,     43,     30,     21,     12,      6,      0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_1[16] = {
+       199,    165,    144,    124,    109,     96,     84,     71,
+        61,     51,     42,     32,     23,     15,      8,      0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_2[32] = {
+       241,    225,    211,    199,    187,    175,    164,    153,
+       142,    132,    123,    114,    105,     96,     88,     80,
+        72,     64,     57,     50,     44,     38,     33,     29,
+        24,     20,     16,     12,      9,      5,      2,      0
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = {
+        15,    131,    138,    138,    155,    155,    173,    173
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = {
+        69,     93,    115,    118,    131,    138,    141,    138,
+       150,    150,    155,    150,    155,    160,    166,    160
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = {
+       131,    128,    134,    141,    141,    141,    145,    145,
+       145,    150,    155,    155,    155,    155,    160,    160,
+       160,    160,    166,    166,    173,    173,    182,    192,
+       182,    192,    192,    192,    205,    192,    205,    224
+};
+
+const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = {
+    silk_LTP_gain_iCDF_0,
+    silk_LTP_gain_iCDF_1,
+    silk_LTP_gain_iCDF_2
+};
+
+const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = {
+    silk_LTP_gain_BITS_Q5_0,
+    silk_LTP_gain_BITS_Q5_1,
+    silk_LTP_gain_BITS_Q5_2
+};
+
+static const opus_int8 silk_LTP_gain_vq_0[8][5] =
+{
+{
+         4,      6,     24,      7,      5
+},
+{
+         0,      0,      2,      0,      0
+},
+{
+        12,     28,     41,     13,     -4
+},
+{
+        -9,     15,     42,     25,     14
+},
+{
+         1,     -2,     62,     41,     -9
+},
+{
+       -10,     37,     65,     -4,      3
+},
+{
+        -6,      4,     66,      7,     -8
+},
+{
+        16,     14,     38,     -3,     33
+}
+};
+
+static const opus_int8 silk_LTP_gain_vq_1[16][5] =
+{
+{
+        13,     22,     39,     23,     12
+},
+{
+        -1,     36,     64,     27,     -6
+},
+{
+        -7,     10,     55,     43,     17
+},
+{
+         1,      1,      8,      1,      1
+},
+{
+         6,    -11,     74,     53,     -9
+},
+{
+       -12,     55,     76,    -12,      8
+},
+{
+        -3,      3,     93,     27,     -4
+},
+{
+        26,     39,     59,      3,     -8
+},
+{
+         2,      0,     77,     11,      9
+},
+{
+        -8,     22,     44,     -6,      7
+},
+{
+        40,      9,     26,      3,      9
+},
+{
+        -7,     20,    101,     -7,      4
+},
+{
+         3,     -8,     42,     26,      0
+},
+{
+       -15,     33,     68,      2,     23
+},
+{
+        -2,     55,     46,     -2,     15
+},
+{
+         3,     -1,     21,     16,     41
+}
+};
+
+static const opus_int8 silk_LTP_gain_vq_2[32][5] =
+{
+{
+        -6,     27,     61,     39,      5
+},
+{
+       -11,     42,     88,      4,      1
+},
+{
+        -2,     60,     65,      6,     -4
+},
+{
+        -1,     -5,     73,     56,      1
+},
+{
+        -9,     19,     94,     29,     -9
+},
+{
+         0,     12,     99,      6,      4
+},
+{
+         8,    -19,    102,     46,    -13
+},
+{
+         3,      2,     13,      3,      2
+},
+{
+         9,    -21,     84,     72,    -18
+},
+{
+       -11,     46,    104,    -22,      8
+},
+{
+        18,     38,     48,     23,      0
+},
+{
+       -16,     70,     83,    -21,     11
+},
+{
+         5,    -11,    117,     22,     -8
+},
+{
+        -6,     23,    117,    -12,      3
+},
+{
+         3,     -8,     95,     28,      4
+},
+{
+       -10,     15,     77,     60,    -15
+},
+{
+        -1,      4,    124,      2,     -4
+},
+{
+         3,     38,     84,     24,    -25
+},
+{
+         2,     13,     42,     13,     31
+},
+{
+        21,     -4,     56,     46,     -1
+},
+{
+        -1,     35,     79,    -13,     19
+},
+{
+        -7,     65,     88,     -9,    -14
+},
+{
+        20,      4,     81,     49,    -29
+},
+{
+        20,      0,     75,      3,    -17
+},
+{
+         5,     -9,     44,     92,     -8
+},
+{
+         1,     -3,     22,     69,     31
+},
+{
+        -6,     95,     41,    -12,      5
+},
+{
+        39,     67,     16,     -4,      1
+},
+{
+         0,     -6,    120,     55,    -36
+},
+{
+       -13,     44,    122,      4,    -24
+},
+{
+        81,      5,     11,      3,      7
+},
+{
+         2,      0,      9,     10,     88
+}
+};
+
+const opus_int8 * const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = {
+    (opus_int8 *)&silk_LTP_gain_vq_0[0][0],
+    (opus_int8 *)&silk_LTP_gain_vq_1[0][0],
+    (opus_int8 *)&silk_LTP_gain_vq_2[0][0]
+};
+
+/* Maximum frequency-dependent response of the pitch taps above,
+   computed as max(abs(freqz(taps))) */
+static const opus_uint8 silk_LTP_gain_vq_0_gain[8] = {
+      46,      2,     90,     87,     93,     91,     82,     98
+};
+
+static const opus_uint8 silk_LTP_gain_vq_1_gain[16] = {
+     109,    120,    118,     12,    113,    115,    117,    119,
+      99,     59,     87,    111,     63,    111,    112,     80
+};
+
+static const opus_uint8 silk_LTP_gain_vq_2_gain[32] = {
+     126,    124,    125,    124,    129,    121,    126,     23,
+     132,    127,    127,    127,    126,    127,    122,    133,
+     130,    134,    101,    118,    119,    145,    126,     86,
+     124,    120,    123,    119,    170,    173,    107,    109
+};
+
+const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS] = {
+    &silk_LTP_gain_vq_0_gain[0],
+    &silk_LTP_gain_vq_1_gain[0],
+    &silk_LTP_gain_vq_2_gain[0]
+};
+
+const opus_int8 silk_LTP_vq_sizes[NB_LTP_CBKS] = {
+    8, 16, 32
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_NB_MB.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_NB_MB.c
new file mode 100644 (file)
index 0000000..195d5b9
--- /dev/null
@@ -0,0 +1,195 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = {
+        12,     35,     60,     83,    108,    132,    157,    180,
+       206,    228,     15,     32,     55,     77,    101,    125,
+       151,    175,    201,    225,     19,     42,     66,     89,
+       114,    137,    162,    184,    209,    230,     12,     25,
+        50,     72,     97,    120,    147,    172,    200,    223,
+        26,     44,     69,     90,    114,    135,    159,    180,
+       205,    225,     13,     22,     53,     80,    106,    130,
+       156,    180,    205,    228,     15,     25,     44,     64,
+        90,    115,    142,    168,    196,    222,     19,     24,
+        62,     82,    100,    120,    145,    168,    190,    214,
+        22,     31,     50,     79,    103,    120,    151,    170,
+       203,    227,     21,     29,     45,     65,    106,    124,
+       150,    171,    196,    224,     30,     49,     75,     97,
+       121,    142,    165,    186,    209,    229,     19,     25,
+        52,     70,     93,    116,    143,    166,    192,    219,
+        26,     34,     62,     75,     97,    118,    145,    167,
+       194,    217,     25,     33,     56,     70,     91,    113,
+       143,    165,    196,    223,     21,     34,     51,     72,
+        97,    117,    145,    171,    196,    222,     20,     29,
+        50,     67,     90,    117,    144,    168,    197,    221,
+        22,     31,     48,     66,     95,    117,    146,    168,
+       196,    222,     24,     33,     51,     77,    116,    134,
+       158,    180,    200,    224,     21,     28,     70,     87,
+       106,    124,    149,    170,    194,    217,     26,     33,
+        53,     64,     83,    117,    152,    173,    204,    225,
+        27,     34,     65,     95,    108,    129,    155,    174,
+       210,    225,     20,     26,     72,     99,    113,    131,
+       154,    176,    200,    219,     34,     43,     61,     78,
+        93,    114,    155,    177,    205,    229,     23,     29,
+        54,     97,    124,    138,    163,    179,    209,    229,
+        30,     38,     56,     89,    118,    129,    158,    178,
+       200,    231,     21,     29,     49,     63,     85,    111,
+       142,    163,    193,    222,     27,     48,     77,    103,
+       133,    158,    179,    196,    215,    232,     29,     47,
+        74,     99,    124,    151,    176,    198,    220,    237,
+        33,     42,     61,     76,     93,    121,    155,    174,
+       207,    225,     29,     53,     87,    112,    136,    154,
+       170,    188,    208,    227,     24,     30,     52,     84,
+       131,    150,    166,    186,    203,    229,     37,     48,
+        64,     84,    104,    118,    156,    177,    201,    230
+};
+
+static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 320 ] = {
+     2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287,
+     2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194,
+     2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354,
+     3216, 2766, 2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194,
+     2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314,
+     3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261,
+     3282, 3141, 2580, 2394, 2247, 2221, 2207, 2194, 2194, 2114,
+     4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074,
+     3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221,
+     3338, 3488, 2726, 2194, 2261, 2460, 2354, 2367, 2207, 2101,
+     2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367,
+     3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048,
+     3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300, 2274, 2127,
+     3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101,
+     2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114,
+     3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
+     3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114,
+     3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181,
+     3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127,
+     3423, 3535, 3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274,
+     3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540,
+     3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261,
+     3028, 3272, 2740, 2888, 2740, 2154, 2127, 2287, 2234, 2247,
+     3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367,
+     3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167,
+     3338, 3366, 2846, 2780, 2327, 2154, 2274, 2287, 2114, 2061,
+     2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553,
+     2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700,
+     3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314, 2354, 2380,
+     2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367,
+     3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207,
+     2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181
+};
+
+static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = {
+       212,    178,    148,    129,    108,     96,     85,     82,
+        79,     77,     61,     59,     57,     56,     51,     49,
+        48,     45,     42,     41,     40,     38,     36,     34,
+        31,     30,     21,     12,     10,      3,      1,      0,
+       255,    245,    244,    236,    233,    225,    217,    203,
+       190,    176,    175,    161,    149,    136,    125,    114,
+       102,     91,     81,     71,     60,     52,     43,     35,
+        28,     20,     19,     18,     12,     11,      5,      0
+};
+
+static const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = {
+        16,      0,      0,      0,      0,     99,     66,     36,
+        36,     34,     36,     34,     34,     34,     34,     83,
+        69,     36,     52,     34,    116,    102,     70,     68,
+        68,    176,    102,     68,     68,     34,     65,     85,
+        68,     84,     36,    116,    141,    152,    139,    170,
+       132,    187,    184,    216,    137,    132,    249,    168,
+       185,    139,    104,    102,    100,     68,     68,    178,
+       218,    185,    185,    170,    244,    216,    187,    187,
+       170,    244,    187,    187,    219,    138,    103,    155,
+       184,    185,    137,    116,    183,    155,    152,    136,
+       132,    217,    184,    184,    170,    164,    217,    171,
+       155,    139,    244,    169,    184,    185,    170,    164,
+       216,    223,    218,    138,    214,    143,    188,    218,
+       168,    244,    141,    136,    155,    170,    168,    138,
+       220,    219,    139,    164,    219,    202,    216,    137,
+       168,    186,    246,    185,    139,    116,    185,    219,
+       185,    138,    100,    100,    134,    100,    102,     34,
+        68,     68,    100,     68,    168,    203,    221,    218,
+       168,    167,    154,    136,    104,     70,    164,    246,
+       171,    137,    139,    137,    155,    218,    219,    139
+};
+
+static const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = {
+       255,    254,    253,    238,     14,      3,      2,      1,
+         0,    255,    254,    252,    218,     35,      3,      2,
+         1,      0,    255,    254,    250,    208,     59,      4,
+         2,      1,      0,    255,    254,    246,    194,     71,
+        10,      2,      1,      0,    255,    252,    236,    183,
+        82,      8,      2,      1,      0,    255,    252,    235,
+       180,     90,     17,      2,      1,      0,    255,    248,
+       224,    171,     97,     30,      4,      1,      0,    255,
+       254,    236,    173,     95,     37,      7,      1,      0
+};
+
+static const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = {
+       255,    255,    255,    131,      6,    145,    255,    255,
+       255,    255,    255,    236,     93,     15,     96,    255,
+       255,    255,    255,    255,    194,     83,     25,     71,
+       221,    255,    255,    255,    255,    162,     73,     34,
+        66,    162,    255,    255,    255,    210,    126,     73,
+        43,     57,    173,    255,    255,    255,    201,    125,
+        71,     48,     58,    130,    255,    255,    255,    166,
+       110,     73,     57,     62,    104,    210,    255,    255,
+       251,    123,     65,     55,     68,    100,    171,    255
+};
+
+static const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = {
+       179,    138,    140,    148,    151,    149,    153,    151,
+       163,    116,     67,     82,     59,     92,     72,    100,
+        89,     92
+};
+
+static const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = {
+       250,      3,      6,      3,      3,      3,      4,      3,
+         3,      3,    461
+};
+
+const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB =
+{
+    32,
+    10,
+    SILK_FIX_CONST( 0.18, 16 ),
+    SILK_FIX_CONST( 1.0 / 0.18, 6 ),
+    silk_NLSF_CB1_NB_MB_Q8,
+    silk_NLSF_CB1_Wght_Q9,
+    silk_NLSF_CB1_iCDF_NB_MB,
+    silk_NLSF_PRED_NB_MB_Q8,
+    silk_NLSF_CB2_SELECT_NB_MB,
+    silk_NLSF_CB2_iCDF_NB_MB,
+    silk_NLSF_CB2_BITS_NB_MB_Q5,
+    silk_NLSF_DELTA_MIN_NB_MB_Q15,
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_WB.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_NLSF_CB_WB.c
new file mode 100644 (file)
index 0000000..4212791
--- /dev/null
@@ -0,0 +1,233 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = {
+         7,     23,     38,     54,     69,     85,    100,    116,
+       131,    147,    162,    178,    193,    208,    223,    239,
+        13,     25,     41,     55,     69,     83,     98,    112,
+       127,    142,    157,    171,    187,    203,    220,    236,
+        15,     21,     34,     51,     61,     78,     92,    106,
+       126,    136,    152,    167,    185,    205,    225,    240,
+        10,     21,     36,     50,     63,     79,     95,    110,
+       126,    141,    157,    173,    189,    205,    221,    237,
+        17,     20,     37,     51,     59,     78,     89,    107,
+       123,    134,    150,    164,    184,    205,    224,    240,
+        10,     15,     32,     51,     67,     81,     96,    112,
+       129,    142,    158,    173,    189,    204,    220,    236,
+         8,     21,     37,     51,     65,     79,     98,    113,
+       126,    138,    155,    168,    179,    192,    209,    218,
+        12,     15,     34,     55,     63,     78,     87,    108,
+       118,    131,    148,    167,    185,    203,    219,    236,
+        16,     19,     32,     36,     56,     79,     91,    108,
+       118,    136,    154,    171,    186,    204,    220,    237,
+        11,     28,     43,     58,     74,     89,    105,    120,
+       135,    150,    165,    180,    196,    211,    226,    241,
+         6,     16,     33,     46,     60,     75,     92,    107,
+       123,    137,    156,    169,    185,    199,    214,    225,
+        11,     19,     30,     44,     57,     74,     89,    105,
+       121,    135,    152,    169,    186,    202,    218,    234,
+        12,     19,     29,     46,     57,     71,     88,    100,
+       120,    132,    148,    165,    182,    199,    216,    233,
+        17,     23,     35,     46,     56,     77,     92,    106,
+       123,    134,    152,    167,    185,    204,    222,    237,
+        14,     17,     45,     53,     63,     75,     89,    107,
+       115,    132,    151,    171,    188,    206,    221,    240,
+         9,     16,     29,     40,     56,     71,     88,    103,
+       119,    137,    154,    171,    189,    205,    222,    237,
+        16,     19,     36,     48,     57,     76,     87,    105,
+       118,    132,    150,    167,    185,    202,    218,    236,
+        12,     17,     29,     54,     71,     81,     94,    104,
+       126,    136,    149,    164,    182,    201,    221,    237,
+        15,     28,     47,     62,     79,     97,    115,    129,
+       142,    155,    168,    180,    194,    208,    223,    238,
+         8,     14,     30,     45,     62,     78,     94,    111,
+       127,    143,    159,    175,    192,    207,    223,    239,
+        17,     30,     49,     62,     79,     92,    107,    119,
+       132,    145,    160,    174,    190,    204,    220,    235,
+        14,     19,     36,     45,     61,     76,     91,    108,
+       121,    138,    154,    172,    189,    205,    222,    238,
+        12,     18,     31,     45,     60,     76,     91,    107,
+       123,    138,    154,    171,    187,    204,    221,    236,
+        13,     17,     31,     43,     53,     70,     83,    103,
+       114,    131,    149,    167,    185,    203,    220,    237,
+        17,     22,     35,     42,     58,     78,     93,    110,
+       125,    139,    155,    170,    188,    206,    224,    240,
+         8,     15,     34,     50,     67,     83,     99,    115,
+       131,    146,    162,    178,    193,    209,    224,    239,
+        13,     16,     41,     66,     73,     86,     95,    111,
+       128,    137,    150,    163,    183,    206,    225,    241,
+        17,     25,     37,     52,     63,     75,     92,    102,
+       119,    132,    144,    160,    175,    191,    212,    231,
+        19,     31,     49,     65,     83,    100,    117,    133,
+       147,    161,    174,    187,    200,    213,    227,    242,
+        18,     31,     52,     68,     88,    103,    117,    126,
+       138,    149,    163,    177,    192,    207,    223,    239,
+        16,     29,     47,     61,     76,     90,    106,    119,
+       133,    147,    161,    176,    193,    209,    224,    240,
+        15,     21,     35,     50,     61,     73,     86,     97,
+       110,    119,    129,    141,    175,    198,    218,    237
+};
+
+static const opus_int16 silk_NLSF_CB1_WB_Wght_Q9[ 512 ] = {
+     3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846,
+     3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
+     3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925,
+     3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
+     5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888,
+     4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
+     3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991,
+     5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
+     5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700,
+     3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
+     4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873,
+     3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
+     3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580,
+     3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
+     5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753,
+     4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
+     5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620,
+     4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
+     3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846,
+     4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
+     2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740,
+     4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
+     4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780,
+     4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
+     4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888,
+     4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
+     5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925,
+     3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
+     2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010,
+     2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
+     3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888,
+     3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607
+};
+
+static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = {
+       225,    204,    201,    184,    183,    175,    158,    154,
+       153,    135,    119,    115,    113,    110,    109,     99,
+        98,     95,     79,     68,     52,     50,     48,     45,
+        43,     32,     31,     27,     18,     10,      3,      0,
+       255,    251,    235,    230,    212,    201,    196,    182,
+       167,    166,    163,    151,    138,    124,    110,    104,
+        90,     78,     76,     70,     69,     57,     45,     34,
+        24,     21,     11,      6,      5,      4,      3,      0
+};
+
+static const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = {
+         0,      0,      0,      0,      0,      0,      0,      1,
+       100,    102,    102,     68,     68,     36,     34,     96,
+       164,    107,    158,    185,    180,    185,    139,    102,
+        64,     66,     36,     34,     34,      0,      1,     32,
+       208,    139,    141,    191,    152,    185,    155,    104,
+        96,    171,    104,    166,    102,    102,    102,    132,
+         1,      0,      0,      0,      0,     16,     16,      0,
+        80,    109,     78,    107,    185,    139,    103,    101,
+       208,    212,    141,    139,    173,    153,    123,    103,
+        36,      0,      0,      0,      0,      0,      0,      1,
+        48,      0,      0,      0,      0,      0,      0,     32,
+        68,    135,    123,    119,    119,    103,     69,     98,
+        68,    103,    120,    118,    118,    102,     71,     98,
+       134,    136,    157,    184,    182,    153,    139,    134,
+       208,    168,    248,     75,    189,    143,    121,    107,
+        32,     49,     34,     34,     34,      0,     17,      2,
+       210,    235,    139,    123,    185,    137,    105,    134,
+        98,    135,    104,    182,    100,    183,    171,    134,
+       100,     70,     68,     70,     66,     66,     34,    131,
+        64,    166,    102,     68,     36,      2,      1,      0,
+       134,    166,    102,     68,     34,     34,     66,    132,
+       212,    246,    158,    139,    107,    107,     87,    102,
+       100,    219,    125,    122,    137,    118,    103,    132,
+       114,    135,    137,    105,    171,    106,     50,     34,
+       164,    214,    141,    143,    185,    151,    121,    103,
+       192,     34,      0,      0,      0,      0,      0,      1,
+       208,    109,     74,    187,    134,    249,    159,    137,
+       102,    110,    154,    118,     87,    101,    119,    101,
+         0,      2,      0,     36,     36,     66,     68,     35,
+        96,    164,    102,    100,     36,      0,      2,     33,
+       167,    138,    174,    102,    100,     84,      2,      2,
+       100,    107,    120,    119,     36,    197,     24,      0
+};
+
+static const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = {
+       255,    254,    253,    244,     12,      3,      2,      1,
+         0,    255,    254,    252,    224,     38,      3,      2,
+         1,      0,    255,    254,    251,    209,     57,      4,
+         2,      1,      0,    255,    254,    244,    195,     69,
+         4,      2,      1,      0,    255,    251,    232,    184,
+        84,      7,      2,      1,      0,    255,    254,    240,
+       186,     86,     14,      2,      1,      0,    255,    254,
+       239,    178,     91,     30,      5,      1,      0,    255,
+       248,    227,    177,    100,     19,      2,      1,      0
+};
+
+static const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = {
+       255,    255,    255,    156,      4,    154,    255,    255,
+       255,    255,    255,    227,    102,     15,     92,    255,
+       255,    255,    255,    255,    213,     83,     24,     72,
+       236,    255,    255,    255,    255,    150,     76,     33,
+        63,    214,    255,    255,    255,    190,    121,     77,
+        43,     55,    185,    255,    255,    255,    245,    137,
+        71,     43,     59,    139,    255,    255,    255,    255,
+       131,     66,     50,     66,    107,    194,    255,    255,
+       166,    116,     76,     55,     53,    125,    255,    255
+};
+
+static const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = {
+       175,    148,    160,    176,    178,    173,    174,    164,
+       177,    174,    196,    182,    198,    192,    182,     68,
+        62,     66,     60,     72,    117,     85,     90,    118,
+       136,    151,    142,    160,    142,    155
+};
+
+static const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = {
+       100,      3,     40,      3,      3,      3,      5,     14,
+        14,     10,     11,      3,      8,      9,      7,      3,
+       347
+};
+
+const silk_NLSF_CB_struct silk_NLSF_CB_WB =
+{
+    32,
+    16,
+    SILK_FIX_CONST( 0.15, 16 ),
+    SILK_FIX_CONST( 1.0 / 0.15, 6 ),
+    silk_NLSF_CB1_WB_Q8,
+    silk_NLSF_CB1_WB_Wght_Q9,
+    silk_NLSF_CB1_iCDF_WB,
+    silk_NLSF_PRED_WB_Q8,
+    silk_NLSF_CB2_SELECT_WB,
+    silk_NLSF_CB2_iCDF_WB,
+    silk_NLSF_CB2_BITS_WB_Q5,
+    silk_NLSF_DELTA_MIN_WB_Q15,
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_gain.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_gain.c
new file mode 100644 (file)
index 0000000..fb2a3ee
--- /dev/null
@@ -0,0 +1,55 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+
+const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ] =
+{
+{
+       224,    112,     44,     15,      3,      2,      1,      0
+},
+{
+       254,    237,    192,    132,     70,     23,      4,      0
+},
+{
+       255,    252,    226,    155,     61,     11,      2,      0
+}
+};
+
+const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ] = {
+       250,    245,    234,    203,     71,     50,     42,     38,
+        35,     33,     31,     29,     28,     27,     26,     25,
+        24,     23,     22,     21,     20,     19,     18,     17,
+        16,     15,     14,     13,     12,     11,     10,      9,
+         8,      7,      6,      5,      4,      3,      2,      1,
+         0
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_other.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_other.c
new file mode 100644 (file)
index 0000000..b558bf7
--- /dev/null
@@ -0,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "structs.h"
+#include "define.h"
+#include "tables.h"
+
+
+/* Tables for stereo predictor coding */
+const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
+    -13732, -10050, -8266, -7526, -6500, -5000, -2950,  -820,
+       820,   2950,  5000,  6500,  7526,  8266, 10050, 13732
+};
+const opus_uint8  silk_stereo_pred_joint_iCDF[ 25 ] = {
+    249, 247, 246, 245, 244,
+    234, 210, 202, 201, 200,
+    197, 174,  82,  59,  56,
+     55,  54,  46,  22,  12,
+     11,  10,   9,   7,   0
+};
+const opus_uint8  silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 };
+
+/* Tables for LBRR flags */
+static const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 };
+static const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 };
+const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = {
+    silk_LBRR_flags_2_iCDF,
+    silk_LBRR_flags_3_iCDF
+};
+
+/* Table for LSB coding */
+const opus_uint8 silk_lsb_iCDF[ 2 ] = { 120, 0 };
+
+/* Tables for LTPScale */
+const opus_uint8 silk_LTPscale_iCDF[ 3 ] = { 128, 64, 0 };
+
+/* Tables for signal type and offset coding */
+const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ] = {
+       232,    158,    10,      0
+};
+const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ] = {
+       230,      0
+};
+
+/* Tables for NLSF interpolation factor */
+const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ] = { 243, 221, 192, 181, 0 };
+
+/* Quantization offsets */
+const opus_int16  silk_Quantization_Offsets_Q10[ 2 ][ 2 ] = {
+    { OFFSET_UVL_Q10, OFFSET_UVH_Q10 }, { OFFSET_VL_Q10, OFFSET_VH_Q10 }
+};
+
+/* Table for LTPScale */
+const opus_int16 silk_LTPScales_table_Q14[ 3 ] = { 15565, 12288, 8192 };
+
+/* Uniform entropy tables */
+const opus_uint8 silk_uniform3_iCDF[ 3 ] = { 171, 85, 0 };
+const opus_uint8 silk_uniform4_iCDF[ 4 ] = { 192, 128, 64, 0 };
+const opus_uint8 silk_uniform5_iCDF[ 5 ] = { 205, 154, 102, 51, 0 };
+const opus_uint8 silk_uniform6_iCDF[ 6 ] = { 213, 171, 128, 85, 43, 0 };
+const opus_uint8 silk_uniform8_iCDF[ 8 ] = { 224, 192, 160, 128, 96, 64, 32, 0 };
+
+const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ] = { 100, 40, 16, 7, 3, 1, 0 };
+
+/*  Elliptic/Cauer filters designed with 0.1 dB passband ripple,
+        80 dB minimum stopband attenuation, and
+        [0.95 : 0.15 : 0.35] normalized cut off frequencies. */
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ] =
+{
+{    250767114,  501534038,  250767114  },
+{    209867381,  419732057,  209867381  },
+{    170987846,  341967853,  170987846  },
+{    131531482,  263046905,  131531482  },
+{     89306658,  178584282,   89306658  }
+};
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ] =
+{
+{    506393414,  239854379  },
+{    411067935,  169683996  },
+{    306733530,  116694253  },
+{    185807084,   77959395  },
+{     35497197,   57401098  }
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pitch_lag.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pitch_lag.c
new file mode 100644 (file)
index 0000000..72490df
--- /dev/null
@@ -0,0 +1,67 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ] = {
+       253,    250,    244,    233,    212,    182,    150,    131,
+       120,    110,     98,     85,     72,     60,     49,     40,
+        32,     25,     19,     15,     13,     11,      9,      8,
+         7,      6,      5,      4,      3,      2,      1,      0
+};
+
+const opus_uint8 silk_pitch_delta_iCDF[21] = {
+       210,    208,    206,    203,    199,    193,    183,    168,
+       142,    104,     74,     52,     37,     27,     20,     14,
+        10,      6,      4,      2,      0
+};
+
+const opus_uint8 silk_pitch_contour_iCDF[34] = {
+       223,    201,    183,    167,    152,    138,    124,    111,
+        98,     88,     79,     70,     62,     56,     50,     44,
+        39,     35,     31,     27,     24,     21,     18,     16,
+        14,     12,     10,      8,      6,      4,      3,      2,
+         1,      0
+};
+
+const opus_uint8 silk_pitch_contour_NB_iCDF[11] = {
+       188,    176,    155,    138,    119,     97,     67,     43,
+        26,     10,      0
+};
+
+const opus_uint8 silk_pitch_contour_10_ms_iCDF[12] = {
+       165,    119,     80,     61,     47,     35,     27,     20,
+        14,      9,      4,      0
+};
+
+const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[3] = {
+       113,     63,      0
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pulses_per_block.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tables_pulses_per_block.c
new file mode 100644 (file)
index 0000000..c7c01c8
--- /dev/null
@@ -0,0 +1,264 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_max_pulses_table[ 4 ] = {
+         8,     10,     12,     16
+};
+
+const opus_uint8 silk_pulses_per_block_iCDF[ 10 ][ 18 ] = {
+{
+       125,     51,     26,     18,     15,     12,     11,     10,
+         9,      8,      7,      6,      5,      4,      3,      2,
+         1,      0
+},
+{
+       198,    105,     45,     22,     15,     12,     11,     10,
+         9,      8,      7,      6,      5,      4,      3,      2,
+         1,      0
+},
+{
+       213,    162,    116,     83,     59,     43,     32,     24,
+        18,     15,     12,      9,      7,      6,      5,      3,
+         2,      0
+},
+{
+       239,    187,    116,     59,     28,     16,     11,     10,
+         9,      8,      7,      6,      5,      4,      3,      2,
+         1,      0
+},
+{
+       250,    229,    188,    135,     86,     51,     30,     19,
+        13,     10,      8,      6,      5,      4,      3,      2,
+         1,      0
+},
+{
+       249,    235,    213,    185,    156,    128,    103,     83,
+        66,     53,     42,     33,     26,     21,     17,     13,
+        10,      0
+},
+{
+       254,    249,    235,    206,    164,    118,     77,     46,
+        27,     16,     10,      7,      5,      4,      3,      2,
+         1,      0
+},
+{
+       255,    253,    249,    239,    220,    191,    156,    119,
+        85,     57,     37,     23,     15,     10,      6,      4,
+         2,      0
+},
+{
+       255,    253,    251,    246,    237,    223,    203,    179,
+       152,    124,     98,     75,     55,     40,     29,     21,
+        15,      0
+},
+{
+       255,    254,    253,    247,    220,    162,    106,     67,
+        42,     28,     18,     12,      9,      6,      4,      3,
+         2,      0
+}
+};
+
+const opus_uint8 silk_pulses_per_block_BITS_Q5[ 9 ][ 18 ] = {
+{
+        31,     57,    107,    160,    205,    205,    255,    255,
+       255,    255,    255,    255,    255,    255,    255,    255,
+       255,    255
+},
+{
+        69,     47,     67,    111,    166,    205,    255,    255,
+       255,    255,    255,    255,    255,    255,    255,    255,
+       255,    255
+},
+{
+        82,     74,     79,     95,    109,    128,    145,    160,
+       173,    205,    205,    205,    224,    255,    255,    224,
+       255,    224
+},
+{
+       125,     74,     59,     69,     97,    141,    182,    255,
+       255,    255,    255,    255,    255,    255,    255,    255,
+       255,    255
+},
+{
+       173,    115,     85,     73,     76,     92,    115,    145,
+       173,    205,    224,    224,    255,    255,    255,    255,
+       255,    255
+},
+{
+       166,    134,    113,    102,    101,    102,    107,    118,
+       125,    138,    145,    155,    166,    182,    192,    192,
+       205,    150
+},
+{
+       224,    182,    134,    101,     83,     79,     85,     97,
+       120,    145,    173,    205,    224,    255,    255,    255,
+       255,    255
+},
+{
+       255,    224,    192,    150,    120,    101,     92,     89,
+        93,    102,    118,    134,    160,    182,    192,    224,
+       224,    224
+},
+{
+       255,    224,    224,    182,    155,    134,    118,    109,
+       104,    102,    106,    111,    118,    131,    145,    160,
+       173,    131
+}
+};
+
+const opus_uint8 silk_rate_levels_iCDF[ 2 ][ 9 ] =
+{
+{
+       241,    190,    178,    132,     87,     74,     41,     14,
+         0
+},
+{
+       223,    193,    157,    140,    106,     57,     39,     18,
+         0
+}
+};
+
+const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ 9 ] =
+{
+{
+       131,     74,    141,     79,     80,    138,     95,    104,
+       134
+},
+{
+        95,     99,     91,    125,     93,     76,    123,    115,
+       123
+}
+};
+
+const opus_uint8 silk_shell_code_table0[ 152 ] = {
+       128,      0,    214,     42,      0,    235,    128,     21,
+         0,    244,    184,     72,     11,      0,    248,    214,
+       128,     42,      7,      0,    248,    225,    170,     80,
+        25,      5,      0,    251,    236,    198,    126,     54,
+        18,      3,      0,    250,    238,    211,    159,     82,
+        35,     15,      5,      0,    250,    231,    203,    168,
+       128,     88,     53,     25,      6,      0,    252,    238,
+       216,    185,    148,    108,     71,     40,     18,      4,
+         0,    253,    243,    225,    199,    166,    128,     90,
+        57,     31,     13,      3,      0,    254,    246,    233,
+       212,    183,    147,    109,     73,     44,     23,     10,
+         2,      0,    255,    250,    240,    223,    198,    166,
+       128,     90,     58,     33,     16,      6,      1,      0,
+       255,    251,    244,    231,    210,    181,    146,    110,
+        75,     46,     25,     12,      5,      1,      0,    255,
+       253,    248,    238,    221,    196,    164,    128,     92,
+        60,     35,     18,      8,      3,      1,      0,    255,
+       253,    249,    242,    229,    208,    180,    146,    110,
+        76,     48,     27,     14,      7,      3,      1,      0
+};
+
+const opus_uint8 silk_shell_code_table1[ 152 ] = {
+       129,      0,    207,     50,      0,    236,    129,     20,
+         0,    245,    185,     72,     10,      0,    249,    213,
+       129,     42,      6,      0,    250,    226,    169,     87,
+        27,      4,      0,    251,    233,    194,    130,     62,
+        20,      4,      0,    250,    236,    207,    160,     99,
+        47,     17,      3,      0,    255,    240,    217,    182,
+       131,     81,     41,     11,      1,      0,    255,    254,
+       233,    201,    159,    107,     61,     20,      2,      1,
+         0,    255,    249,    233,    206,    170,    128,     86,
+        50,     23,      7,      1,      0,    255,    250,    238,
+       217,    186,    148,    108,     70,     39,     18,      6,
+         1,      0,    255,    252,    243,    226,    200,    166,
+       128,     90,     56,     30,     13,      4,      1,      0,
+       255,    252,    245,    231,    209,    180,    146,    110,
+        76,     47,     25,     11,      4,      1,      0,    255,
+       253,    248,    237,    219,    194,    163,    128,     93,
+        62,     37,     19,      8,      3,      1,      0,    255,
+       254,    250,    241,    226,    205,    177,    145,    111,
+        79,     51,     30,     15,      6,      2,      1,      0
+};
+
+const opus_uint8 silk_shell_code_table2[ 152 ] = {
+       129,      0,    203,     54,      0,    234,    129,     23,
+         0,    245,    184,     73,     10,      0,    250,    215,
+       129,     41,      5,      0,    252,    232,    173,     86,
+        24,      3,      0,    253,    240,    200,    129,     56,
+        15,      2,      0,    253,    244,    217,    164,     94,
+        38,     10,      1,      0,    253,    245,    226,    189,
+       132,     71,     27,      7,      1,      0,    253,    246,
+       231,    203,    159,    105,     56,     23,      6,      1,
+         0,    255,    248,    235,    213,    179,    133,     85,
+        47,     19,      5,      1,      0,    255,    254,    243,
+       221,    194,    159,    117,     70,     37,     12,      2,
+         1,      0,    255,    254,    248,    234,    208,    171,
+       128,     85,     48,     22,      8,      2,      1,      0,
+       255,    254,    250,    240,    220,    189,    149,    107,
+        67,     36,     16,      6,      2,      1,      0,    255,
+       254,    251,    243,    227,    201,    166,    128,     90,
+        55,     29,     13,      5,      2,      1,      0,    255,
+       254,    252,    246,    234,    213,    183,    147,    109,
+        73,     43,     22,     10,      4,      2,      1,      0
+};
+
+const opus_uint8 silk_shell_code_table3[ 152 ] = {
+       130,      0,    200,     58,      0,    231,    130,     26,
+         0,    244,    184,     76,     12,      0,    249,    214,
+       130,     43,      6,      0,    252,    232,    173,     87,
+        24,      3,      0,    253,    241,    203,    131,     56,
+        14,      2,      0,    254,    246,    221,    167,     94,
+        35,      8,      1,      0,    254,    249,    232,    193,
+       130,     65,     23,      5,      1,      0,    255,    251,
+       239,    211,    162,     99,     45,     15,      4,      1,
+         0,    255,    251,    243,    223,    186,    131,     74,
+        33,     11,      3,      1,      0,    255,    252,    245,
+       230,    202,    158,    105,     57,     24,      8,      2,
+         1,      0,    255,    253,    247,    235,    214,    179,
+       132,     84,     44,     19,      7,      2,      1,      0,
+       255,    254,    250,    240,    223,    196,    159,    112,
+        69,     36,     15,      6,      2,      1,      0,    255,
+       254,    253,    245,    231,    209,    176,    136,     93,
+        55,     27,     11,      3,      2,      1,      0,    255,
+       254,    253,    252,    239,    221,    194,    158,    117,
+        76,     42,     18,      4,      3,      2,      1,      0
+};
+
+const opus_uint8 silk_shell_code_table_offsets[ 17 ] = {
+         0,      0,      2,      5,      9,     14,     20,     27,
+        35,     44,     54,     65,     77,     90,    104,    119,
+       135
+};
+
+const opus_uint8 silk_sign_iCDF[ 42 ] = {
+       254,     49,     67,     77,     82,     93,     99,
+       198,     11,     18,     24,     31,     36,     45,
+       255,     46,     66,     78,     87,     94,    104,
+       208,     14,     21,     32,     42,     51,     66,
+       255,     94,    104,    109,    112,    115,    118,
+       248,     53,     69,     80,     88,     95,    102
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tuning_parameters.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/tuning_parameters.h
new file mode 100644 (file)
index 0000000..e2a23eb
--- /dev/null
@@ -0,0 +1,146 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_TUNING_PARAMETERS_H
+#define SILK_TUNING_PARAMETERS_H
+
+/* Decay time for bitreservoir */
+#define BITRESERVOIR_DECAY_TIME_MS                      500
+
+/*******************/
+/* Pitch estimator */
+/*******************/
+
+/* Level of noise floor for whitening filter LPC analysis in pitch analysis */
+#define FIND_PITCH_WHITE_NOISE_FRACTION                 1e-3f
+
+/* Bandwidth expansion for whitening filter in pitch analysis */
+#define FIND_PITCH_BANDWIDTH_EXPANSION                  0.99f
+
+/*********************/
+/* Linear prediction */
+/*********************/
+
+/* LPC analysis regularization */
+#define FIND_LPC_COND_FAC                               1e-5f
+
+/* Max cumulative LTP gain */
+#define MAX_SUM_LOG_GAIN_DB                             250.0f
+
+/* LTP analysis defines */
+#define LTP_CORR_INV_MAX                                0.03f
+
+/***********************/
+/* High pass filtering */
+/***********************/
+
+/* Smoothing parameters for low end of pitch frequency range estimation */
+#define VARIABLE_HP_SMTH_COEF1                          0.1f
+#define VARIABLE_HP_SMTH_COEF2                          0.015f
+#define VARIABLE_HP_MAX_DELTA_FREQ                      0.4f
+
+/* Min and max cut-off frequency values (-3 dB points) */
+#define VARIABLE_HP_MIN_CUTOFF_HZ                       60
+#define VARIABLE_HP_MAX_CUTOFF_HZ                       100
+
+/***********/
+/* Various */
+/***********/
+
+/* VAD threshold */
+#define SPEECH_ACTIVITY_DTX_THRES                       0.05f
+
+/* Speech Activity LBRR enable threshold */
+#define LBRR_SPEECH_ACTIVITY_THRES                      0.3f
+
+/*************************/
+/* Perceptual parameters */
+/*************************/
+
+/* reduction in coding SNR during low speech activity */
+#define BG_SNR_DECR_dB                                  2.0f
+
+/* factor for reducing quantization noise during voiced speech */
+#define HARM_SNR_INCR_dB                                2.0f
+
+/* factor for reducing quantization noise for unvoiced sparse signals */
+#define SPARSE_SNR_INCR_dB                              2.0f
+
+/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */
+#define ENERGY_VARIATION_THRESHOLD_QNT_OFFSET           0.6f
+
+/* warping control */
+#define WARPING_MULTIPLIER                              0.015f
+
+/* fraction added to first autocorrelation value */
+#define SHAPE_WHITE_NOISE_FRACTION                      3e-5f
+
+/* noise shaping filter chirp factor */
+#define BANDWIDTH_EXPANSION                             0.94f
+
+/* harmonic noise shaping */
+#define HARMONIC_SHAPING                                0.3f
+
+/* extra harmonic noise shaping for high bitrates or noisy input */
+#define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING       0.2f
+
+/* parameter for shaping noise towards higher frequencies */
+#define HP_NOISE_COEF                                   0.25f
+
+/* parameter for shaping noise even more towards higher frequencies during voiced speech */
+#define HARM_HP_NOISE_COEF                              0.35f
+
+/* parameter for applying a high-pass tilt to the input signal */
+#define INPUT_TILT                                      0.05f
+
+/* parameter for extra high-pass tilt to the input signal at high rates */
+#define HIGH_RATE_INPUT_TILT                            0.1f
+
+/* parameter for reducing noise at the very low frequencies */
+#define LOW_FREQ_SHAPING                                4.0f
+
+/* less reduction of noise at the very low frequencies for signals with low SNR at low frequencies */
+#define LOW_QUALITY_LOW_FREQ_SHAPING_DECR               0.5f
+
+/* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */
+#define SUBFR_SMTH_COEF                                 0.4f
+
+/* parameters defining the R/D tradeoff in the residual quantizer */
+#define LAMBDA_OFFSET                                   1.2f
+#define LAMBDA_SPEECH_ACT                               -0.2f
+#define LAMBDA_DELAYED_DECISIONS                        -0.05f
+#define LAMBDA_INPUT_QUALITY                            -0.1f
+#define LAMBDA_CODING_QUALITY                           -0.2f
+#define LAMBDA_QUANT_OFFSET                             0.8f
+
+/* Compensation in bitrate calculations for 10 ms modes */
+#define REDUCE_BITRATE_10_MS_BPS                        2200
+
+/* Maximum time before allowing a bandwidth transition */
+#define MAX_BANDWIDTH_SWITCH_DELAY_MS                   5000
+
+#endif /* SILK_TUNING_PARAMETERS_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/typedef.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/typedef.h
new file mode 100644 (file)
index 0000000..1c712df
--- /dev/null
@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_TYPEDEF_H
+#define SILK_TYPEDEF_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#ifndef FIXED_POINT
+# include <float.h>
+# define silk_float      float
+# define silk_float_MAX  FLT_MAX
+#endif
+
+#define silk_int64_MAX   ((opus_int64)0x7FFFFFFFFFFFFFFFLL)   /*  2^63 - 1 */
+#define silk_int64_MIN   ((opus_int64)0x8000000000000000LL)   /* -2^63 */
+#define silk_int32_MAX   0x7FFFFFFF                           /*  2^31 - 1 =  2147483647 */
+#define silk_int32_MIN   ((opus_int32)0x80000000)             /* -2^31     = -2147483648 */
+#define silk_int16_MAX   0x7FFF                               /*  2^15 - 1 =  32767 */
+#define silk_int16_MIN   ((opus_int16)0x8000)                 /* -2^15     = -32768 */
+#define silk_int8_MAX    0x7F                                 /*  2^7 - 1  =  127 */
+#define silk_int8_MIN    ((opus_int8)0x80)                    /* -2^7      = -128 */
+#define silk_uint8_MAX   0xFF                                 /*  2^8 - 1 = 255 */
+
+#define silk_TRUE        1
+#define silk_FALSE       0
+
+/* assertions */
+#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS))
+# ifndef silk_assert
+#  include <crtdbg.h>      /* ASSERTE() */
+#  define silk_assert(COND)   _ASSERTE(COND)
+# endif
+#else
+# ifdef ENABLE_ASSERTIONS
+#  include <stdio.h>
+#  include <stdlib.h>
+#define silk_fatal(str) _silk_fatal(str, __FILE__, __LINE__);
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+static OPUS_INLINE void _silk_fatal(const char *str, const char *file, int line)
+{
+   fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+#if defined(_MSC_VER)
+   _set_abort_behavior( 0, _WRITE_ABORT_MSG);
+#endif
+   abort();
+}
+#  define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}}
+# else
+#  define silk_assert(COND) ((void)(COND))
+# endif
+#endif
+
+#endif /* SILK_TYPEDEF_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_arm.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_arm.h
new file mode 100644 (file)
index 0000000..1992e43
--- /dev/null
@@ -0,0 +1,68 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(FIXED_POINT)
+
+#  if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_warped_autocorrelation_FIX_neon(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#   define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
+#  endif
+#  endif
+
+#  if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+/*Is run-time CPU detection enabled on this platform?*/
+#   if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
+#    define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#    define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
+#   elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#    define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#    define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
+#   endif
+#  endif
+
+# endif /* end FIXED_POINT */
+
+#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_mipsr1.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/warped_autocorrelation_FIX_mipsr1.h
new file mode 100644 (file)
index 0000000..9d9cb05
--- /dev/null
@@ -0,0 +1,189 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__
+#define __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FIX.h"
+
+#if defined (__mips_dsp) && __mips == 32
+
+#define MIPS_MADD __builtin_mips_madd
+#define MIPS_SHILO __builtin_mips_shilo
+
+#define OVERRIDE_silk_warped_autocorrelation_FIX_c
+
+#elif defined (__mips_isa_rev) && __mips == 32
+
+static inline long long MIPS_MADD(long long acc, int a, int b) {
+    return acc + (long long)a * b;
+}
+
+static inline long long MIPS_SHILO(long long acc, int sh) {
+    return (sh >= 0) ? (acc >> sh) : (acc << -sh);
+}
+
+#define OVERRIDE_silk_warped_autocorrelation_FIX_c
+
+#endif
+
+/* Autocorrelations for a warped frequency axis */
+#if defined (OVERRIDE_silk_warped_autocorrelation_FIX_c)
+
+#undef QC
+#define QC  10
+
+#undef QS
+#define QS  14
+
+void silk_warped_autocorrelation_FIX_c(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+)
+{
+    opus_int   n, i, lsh;
+    opus_int32 tmp1_QS=0, tmp2_QS=0, tmp3_QS=0, tmp4_QS=0, tmp5_QS=0, tmp6_QS=0, tmp7_QS=0, tmp8_QS=0, start_1=0, start_2=0, start_3=0;
+    opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+    opus_int64 corr_QC[  MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+    opus_int64 temp64;
+
+    opus_int32 val;
+    val = 2 * QS - QC;
+
+    /* Order must be even */
+    silk_assert( ( order & 1 ) == 0 );
+    silk_assert( 2 * QS - QC >= 0 );
+
+    /* Loop over samples */
+    for( n = 0; n < length; n=n+4 ) {
+
+        tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+        start_1 = tmp1_QS;
+        tmp3_QS = silk_LSHIFT32( (opus_int32)input[ n+1], QS );
+        start_2 = tmp3_QS;
+        tmp5_QS = silk_LSHIFT32( (opus_int32)input[ n+2], QS );
+        start_3 = tmp5_QS;
+        tmp7_QS = silk_LSHIFT32( (opus_int32)input[ n+3], QS );
+
+        /* Loop over allpass sections */
+        for( i = 0; i < order; i += 2 ) {
+            /* Output of allpass section */
+            tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 );
+            corr_QC[  i ] = MIPS_MADD( corr_QC[  i ], tmp1_QS,  start_1);
+
+            tmp4_QS = silk_SMLAWB( tmp1_QS, tmp2_QS - tmp3_QS, warping_Q16 );
+            corr_QC[  i ] = MIPS_MADD( corr_QC[  i ], tmp3_QS,  start_2);
+
+            tmp6_QS = silk_SMLAWB( tmp3_QS, tmp4_QS - tmp5_QS, warping_Q16 );
+            corr_QC[  i ] = MIPS_MADD( corr_QC[  i ], tmp5_QS,  start_3);
+
+            tmp8_QS = silk_SMLAWB( tmp5_QS, tmp6_QS - tmp7_QS, warping_Q16 );
+            state_QS[ i ]  = tmp7_QS;
+            corr_QC[  i ] = MIPS_MADD( corr_QC[  i ], tmp7_QS, state_QS[0]);
+
+            /* Output of allpass section */
+            tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 );
+            corr_QC[  i+1 ] = MIPS_MADD( corr_QC[  i+1 ], tmp2_QS,  start_1);
+
+            tmp3_QS = silk_SMLAWB( tmp2_QS, tmp1_QS - tmp4_QS, warping_Q16 );
+            corr_QC[  i+1 ] = MIPS_MADD( corr_QC[  i+1 ], tmp4_QS,  start_2);
+
+            tmp5_QS = silk_SMLAWB( tmp4_QS, tmp3_QS - tmp6_QS, warping_Q16 );
+            corr_QC[  i+1 ] = MIPS_MADD( corr_QC[  i+1 ], tmp6_QS,  start_3);
+
+            tmp7_QS = silk_SMLAWB( tmp6_QS, tmp5_QS - tmp8_QS, warping_Q16 );
+            state_QS[ i + 1 ]  = tmp8_QS;
+            corr_QC[  i+1 ] = MIPS_MADD( corr_QC[  i+1 ], tmp8_QS,  state_QS[ 0 ]);
+
+        }
+        state_QS[ order ] = tmp7_QS;
+
+        corr_QC[  order ] = MIPS_MADD( corr_QC[  order ], tmp1_QS,  start_1);
+        corr_QC[  order ] = MIPS_MADD( corr_QC[  order ], tmp3_QS,  start_2);
+        corr_QC[  order ] = MIPS_MADD( corr_QC[  order ], tmp5_QS,  start_3);
+        corr_QC[  order ] = MIPS_MADD( corr_QC[  order ], tmp7_QS,  state_QS[ 0 ]);
+    }
+
+    for(;n< length; n++ ) {
+
+        tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+
+        /* Loop over allpass sections */
+        for( i = 0; i < order; i += 2 ) {
+
+            /* Output of allpass section */
+            tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 );
+            state_QS[ i ] = tmp1_QS;
+            corr_QC[  i ] = MIPS_MADD( corr_QC[  i ], tmp1_QS,   state_QS[ 0 ]);
+
+            /* Output of allpass section */
+            tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 );
+            state_QS[ i + 1 ]  = tmp2_QS;
+            corr_QC[  i+1 ] = MIPS_MADD( corr_QC[  i+1 ], tmp2_QS,   state_QS[ 0 ]);
+        }
+        state_QS[ order ] = tmp1_QS;
+        corr_QC[  order ] = MIPS_MADD( corr_QC[  order ], tmp1_QS,   state_QS[ 0 ]);
+    }
+
+    temp64 =  corr_QC[ 0 ];
+    temp64 = MIPS_SHILO(temp64, val);
+
+    lsh = silk_CLZ64( temp64 ) - 35;
+    lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
+    *scale = -( QC + lsh );
+    silk_assert( *scale >= -30 && *scale <= 12 );
+    if( lsh >= 0 ) {
+        for( i = 0; i < order + 1; i++ ) {
+            temp64 = corr_QC[ i ];
+            //temp64 = MIPS_SHILO(temp64, val);
+            temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val);
+            corr[ i ] = (opus_int32)silk_CHECK_FIT32( MIPS_SHILO( temp64, -lsh ) );
+        }
+    } else {
+        for( i = 0; i < order + 1; i++ ) {
+            temp64 = corr_QC[ i ];
+            //temp64 = MIPS_SHILO(temp64, val);
+            temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val);
+            corr[ i ] = (opus_int32)silk_CHECK_FIT32( MIPS_SHILO( temp64, -lsh ) );
+        }
+    }
+
+     corr_QC[ 0 ] = MIPS_SHILO(corr_QC[ 0 ], val);
+
+     silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
+}
+#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
+
+#endif /* __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/SigProc_FIX_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/SigProc_FIX_sse.h
new file mode 100644 (file)
index 0000000..89a5ec8
--- /dev/null
@@ -0,0 +1,99 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SIGPROC_FIX_SSE_H
+# define SIGPROC_FIX_SSE_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+void silk_burg_modified_sse4_1(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_burg_modified
+#   define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+       ((void)(arch), silk_burg_modified_sse4_1(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */);
+
+#   define OVERRIDE_silk_burg_modified
+#   define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+     ((*SILK_BURG_MODIFIED_IMPL[(arch) & OPUS_ARCHMASK])(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+#  endif
+
+opus_int64 silk_inner_prod16_sse4_1(
+    const opus_int16 *inVec1,
+    const opus_int16 *inVec2,
+    const opus_int   len
+);
+
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_inner_prod16
+#   define silk_inner_prod16(inVec1, inVec2, len, arch) \
+       ((void)(arch),silk_inner_prod16_sse4_1(inVec1, inVec2, len))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int64 (*const SILK_INNER_PROD16_IMPL[OPUS_ARCHMASK + 1])(
+                    const opus_int16 *inVec1,
+                    const opus_int16 *inVec2,
+                    const opus_int   len);
+
+#   define OVERRIDE_silk_inner_prod16
+#   define silk_inner_prod16(inVec1, inVec2, len, arch) \
+     ((*SILK_INNER_PROD16_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
+
+#  endif
+# endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/main_sse.h b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/main_sse.h
new file mode 100644 (file)
index 0000000..b254d53
--- /dev/null
@@ -0,0 +1,299 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MAIN_SSE_H
+# define MAIN_SSE_H
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+
+void silk_VQ_WMat_EC_sse4_1(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+);
+
+#  if defined OPUS_X86_PRESUME_SSE4_1
+
+#   define OVERRIDE_silk_VQ_WMat_EC
+#   define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                           subfr_len, max_gain_Q7, L, arch) \
+    ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                          subfr_len, max_gain_Q7, L))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+);
+
+#   define OVERRIDE_silk_VQ_WMat_EC
+#   define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                           subfr_len, max_gain_Q7, L, arch) \
+    ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+                          subfr_len, max_gain_Q7, L))
+
+#  endif
+
+void silk_NSQ_sse4_1(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#  if defined OPUS_X86_PRESUME_SSE4_1
+
+#   define OVERRIDE_silk_NSQ
+#   define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#   define OVERRIDE_silk_NSQ
+#   define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+                   HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  endif
+
+void silk_NSQ_del_dec_sse4_1(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+void silk_NSQ_del_dec_avx2(
+    const silk_encoder_state *psEncC,                            /* I    Encoder State               */
+    silk_nsq_state *NSQ,                                         /* I/O  NSQ state                   */
+    SideInfoIndices *psIndices,                                  /* I/O  Quantization Indices        */
+    const opus_int16 x16[],                                      /* I    Input                       */
+    opus_int8 pulses[],                                          /* O    Quantized pulse signal      */
+    const opus_int16 *PredCoef_Q12,                              /* I    Short term prediction coefs */
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],      /* I    Long term prediction coefs  */
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER], /* I    Noise shaping coefs         */
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],              /* I    Long term shaping coefs     */
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],                       /* I    Spectral tilt               */
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],                   /* I    Low frequency shaping coefs */
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],                    /* I    Quantization step sizes     */
+    const opus_int32 pitchL[MAX_NB_SUBFR],                       /* I    Pitch lags                  */
+    const opus_int Lambda_Q10,                                   /* I    Rate/distortion tradeoff    */
+    const opus_int LTP_scale_Q14                                 /* I    LTP state scaling           */
+);
+
+#  if defined (OPUS_X86_PRESUME_AVX2)
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_del_dec_avx2(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined (OPUS_X86_PRESUME_SSE4_1) && !defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+);
+
+#   define OVERRIDE_silk_NSQ_del_dec
+#   define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+    ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+                           HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+#  endif
+
+void silk_noise_shape_quantizer(
+    silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
+    opus_int            signalType,             /* I    Signal type                     */
+    const opus_int32    x_sc_Q10[],             /* I                                    */
+    opus_int8           pulses[],               /* O                                    */
+    opus_int16          xq[],                   /* O                                    */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP state                       */
+    const opus_int16    a_Q12[],                /* I    Short term prediction coefs     */
+    const opus_int16    b_Q14[],                /* I    Long term prediction coefs      */
+    const opus_int16    AR_shp_Q13[],           /* I    Noise shaping AR coefs          */
+    opus_int            lag,                    /* I    Pitch lag                       */
+    opus_int32          HarmShapeFIRPacked_Q14, /* I                                    */
+    opus_int            Tilt_Q14,               /* I    Spectral tilt                   */
+    opus_int32          LF_shp_Q14,             /* I                                    */
+    opus_int32          Gain_Q16,               /* I                                    */
+    opus_int            Lambda_Q10,             /* I                                    */
+    opus_int            offset_Q10,             /* I                                    */
+    opus_int            length,                 /* I    Input length                    */
+    opus_int            shapingLPCOrder,        /* I    Noise shaping AR filter order   */
+    opus_int            predictLPCOrder,        /* I    Prediction filter order         */
+    int                 arch                    /* I    Architecture                    */
+);
+
+/**************************/
+/* Noise level estimation */
+/**************************/
+void silk_VAD_GetNoiseLevels(
+    const opus_int32            pX[ VAD_N_BANDS ],  /* I    subband energies                            */
+    silk_VAD_state              *psSilk_VAD         /* I/O  Pointer to Silk VAD state                   */
+);
+
+opus_int silk_VAD_GetSA_Q8_sse4_1(
+    silk_encoder_state *psEnC,
+    const opus_int16   pIn[]
+);
+
+#  if defined(OPUS_X86_PRESUME_SSE4_1)
+
+#   define OVERRIDE_silk_VAD_GetSA_Q8
+#   define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn))
+
+#  elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
+     silk_encoder_state *psEnC,
+     const opus_int16   pIn[]);
+
+#   define OVERRIDE_silk_VAD_GetSA_Q8
+#   define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
+      ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
+
+#  endif
+
+#ifndef FIXED_POINT
+double silk_inner_product_FLP_avx2(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+);
+
+#if defined (OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_avx2(data1, data2, dataSize))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+extern double (*const SILK_INNER_PRODUCT_FLP_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+);
+
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,(*SILK_INNER_PRODUCT_FLP_IMPL[(arch) & OPUS_ARCHMASK])(data1, data2, dataSize))
+
+#endif
+#endif
+
+# endif
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/x86_silk_map.c b/code/sdk/zhihui/test_opus_frame_to_pcm/silk/x86/x86_silk_map.c
new file mode 100644 (file)
index 0000000..39ad752
--- /dev/null
@@ -0,0 +1,179 @@
+/* Copyright (c) 2014, Cisco Systems, INC
+   Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include "celt/x86/x86cpu.h"
+#include "structs.h"
+#include "SigProc_FIX.h"
+#ifndef FIXED_POINT
+#include "SigProc_FLP.h"
+#endif
+#include "pitch.h"
+#include "main.h"
+
+#if defined(OPUS_HAVE_RTCD) && !defined(OPUS_X86_PRESUME_AVX2)
+
+#if defined(FIXED_POINT)
+
+#include "fixed/main_FIX.h"
+
+opus_int64 (*const SILK_INNER_PROD16_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    const opus_int16 *inVec1,
+    const opus_int16 *inVec2,
+    const opus_int   len
+) = {
+  silk_inner_prod16_c,                  /* non-sse */
+  silk_inner_prod16_c,
+  silk_inner_prod16_c,
+  MAY_HAVE_SSE4_1( silk_inner_prod16 ), /* sse4.1 */
+  MAY_HAVE_SSE4_1( silk_inner_prod16 )  /* avx */
+};
+
+#endif
+
+opus_int (*const SILK_VAD_GETSA_Q8_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    silk_encoder_state *psEncC,
+    const opus_int16   pIn[]
+) = {
+  silk_VAD_GetSA_Q8_c,                  /* non-sse */
+  silk_VAD_GetSA_Q8_c,
+  silk_VAD_GetSA_Q8_c,
+  MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ), /* sse4.1 */
+  MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 )  /* avx */
+};
+
+void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+) = {
+  silk_NSQ_c,                  /* non-sse */
+  silk_NSQ_c,
+  silk_NSQ_c,
+  MAY_HAVE_SSE4_1( silk_NSQ ), /* sse4.1 */
+  MAY_HAVE_SSE4_1( silk_NSQ )  /* avx */
+};
+
+void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    opus_int8                   *ind,                           /* O    index of best codebook vector               */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
+    opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
+    const opus_int8             *cb_Q7,                         /* I    codebook                                    */
+    const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
+    const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
+    const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
+    const opus_int              L                               /* I    number of vectors in codebook               */
+) = {
+  silk_VQ_WMat_EC_c,                  /* non-sse */
+  silk_VQ_WMat_EC_c,
+  silk_VQ_WMat_EC_c,
+  MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ), /* sse4.1 */
+  MAY_HAVE_SSE4_1( silk_VQ_WMat_EC )  /* avx */
+};
+
+void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    const silk_encoder_state    *psEncC,                                      /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                         /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                   /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                        /* I    Input                           */
+    opus_int8                   pulses[],                                     /* O    Quantized pulse signal          */
+    const opus_int16            *PredCoef_Q12,                                /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I    Noise shaping coefs             */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],            /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                     /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                   /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                    /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                       /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                   /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                                 /* I    LTP state scaling               */
+) = {
+  silk_NSQ_del_dec_c,                  /* non-sse */
+  silk_NSQ_del_dec_c,
+  silk_NSQ_del_dec_c,
+  MAY_HAVE_SSE4_1( silk_NSQ_del_dec ), /* sse4.1 */
+  MAY_HAVE_AVX2( silk_NSQ_del_dec )  /* avx */
+};
+
+#if defined(FIXED_POINT)
+
+void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    opus_int32                  *res_nrg,           /* O    Residual energy                                             */
+    opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
+    opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
+    const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
+    const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
+    const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
+    const opus_int              D,                  /* I    Order                                                       */
+    int                         arch                /* I    Run-time architecture                                       */
+) = {
+  silk_burg_modified_c,                  /* non-sse */
+  silk_burg_modified_c,
+  silk_burg_modified_c,
+  MAY_HAVE_SSE4_1( silk_burg_modified ), /* sse4.1 */
+  MAY_HAVE_SSE4_1( silk_burg_modified )  /* avx */
+};
+
+#endif
+
+#ifndef FIXED_POINT
+
+double (*const SILK_INNER_PRODUCT_FLP_IMPL[ OPUS_ARCHMASK + 1 ] )(
+    const silk_float    *data1,
+    const silk_float    *data2,
+    opus_int            dataSize
+) = {
+  silk_inner_product_FLP_c,                  /* non-sse */
+  silk_inner_product_FLP_c,
+  silk_inner_product_FLP_c,
+  silk_inner_product_FLP_c, /* sse4.1 */
+  MAY_HAVE_AVX2( silk_inner_product_FLP )  /* avx */
+};
+
+#endif
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src/opus_frame_to_pcm.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src/opus_frame_to_pcm.c
new file mode 100644 (file)
index 0000000..bdcdf19
--- /dev/null
@@ -0,0 +1,186 @@
+/* Copyright (c) 2007-2008 CSIRO\r
+   Copyright (c) 2007-2009 Xiph.Org Foundation\r
+   Written by Jean-Marc Valin */\r
+/*\r
+   Redistribution and use in source and binary forms, with or without\r
+   modification, are permitted provided that the following conditions\r
+   are met:\r
+\r
+   - Redistributions of source code must retain the above copyright\r
+   notice, this list of conditions and the following disclaimer.\r
+\r
+   - Redistributions in binary form must reproduce the above copyright\r
+   notice, this list of conditions and the following disclaimer in the\r
+   documentation and/or other materials provided with the distribution.\r
+\r
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER\r
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include "opus.h"\r
+\r
+#include "opus_frame_to_pcm.h"\r
+\r
+#define MAX_PACKET_SIZE 15000\r
+#define MAX_PCM_SAMPLES 5760  /* 120ms at 48kHz */\r
+\r
+int opus_frame_to_pcm_decode_packet(const unsigned char *packet_data, int packet_len,\r
+                                    int sample_rate, int channels,\r
+                                    short *out_pcm, int out_pcm_capacity,\r
+                                    int *out_pcm_samples)\r
+{\r
+    OpusDecoder *decoder = NULL;\r
+    int error = OPUS_OK;\r
+    int decoded_samples = 0;\r
+    int total_samples = 0;\r
+\r
+    if (!packet_data || packet_len <= 0 || !out_pcm || out_pcm_capacity <= 0 || !out_pcm_samples) {\r
+        return 1;\r
+    }\r
+    \r
+    /* Validate packet */\r
+    unsigned char out_toc;\r
+    const unsigned char *frames[48];\r
+    opus_int16 size[48];\r
+    int payload_offset;\r
+    int nb_frames = opus_packet_parse(packet_data, packet_len, &out_toc, frames, size, &payload_offset);\r
+    \r
+    if (nb_frames < 0) {\r
+        return 1;\r
+    }\r
+    \r
+    /* Try to get channel count from packet if not specified */\r
+    if (channels <= 0) {\r
+        int packet_channels = opus_packet_get_nb_channels(packet_data);\r
+        if (packet_channels > 0) {\r
+            channels = packet_channels;\r
+        } else {\r
+            channels = 1;  /* Default to mono */\r
+        }\r
+    }\r
+    \r
+    /* Create decoder */\r
+    decoder = opus_decoder_create(sample_rate, channels, &error);\r
+    if (error != OPUS_OK) {\r
+        return 1;\r
+    }\r
+\r
+    /* Decode packet */\r
+    decoded_samples = opus_decode(decoder, packet_data, packet_len, (opus_int16 *)out_pcm, MAX_PCM_SAMPLES, 0);\r
+    if (decoded_samples <= 0) {\r
+        opus_decoder_destroy(decoder);\r
+        return 1;\r
+    }\r
+\r
+    total_samples = decoded_samples * channels;\r
+    if (total_samples > out_pcm_capacity) {\r
+        opus_decoder_destroy(decoder);\r
+        return 1;\r
+    }\r
+    *out_pcm_samples = total_samples;\r
+\r
+    /* Cleanup */\r
+    opus_decoder_destroy(decoder);\r
+    return 0;\r
+}\r
+\r
+/* Decode a single Opus frame file to PCM */\r
+int opus_frame_to_pcm_decode_file(const char *input_file, int sample_rate, int channels,\r
+                                  const char *output_file)\r
+{\r
+    unsigned char *packet_data = NULL;\r
+    int packet_len = 0;\r
+    opus_int16 *pcm = NULL;\r
+    FILE *fin = NULL;\r
+    FILE *fout = NULL;\r
+    int pcm_samples = 0;\r
+\r
+    if (!input_file) {\r
+        return 1;\r
+    }\r
+\r
+    fin = fopen(input_file, "rb");\r
+    if (!fin) {\r
+        return 1;\r
+    }\r
+\r
+    packet_data = (unsigned char *)malloc(MAX_PACKET_SIZE);\r
+    if (!packet_data) {\r
+        fclose(fin);\r
+        return 1;\r
+    }\r
+\r
+    packet_len = fread(packet_data, 1, MAX_PACKET_SIZE, fin);\r
+    fclose(fin);\r
+    fin = NULL;\r
+    if (packet_len <= 0) {\r
+        free(packet_data);\r
+        return 1;\r
+    }\r
+\r
+    /* worst-case output buffer */\r
+    if (channels <= 0) {\r
+        channels = 2; /* allocate enough; decode_packet will detect actual channels */\r
+    }\r
+    pcm = (opus_int16 *)malloc(MAX_PCM_SAMPLES * channels * sizeof(opus_int16));\r
+    if (!pcm) {\r
+        free(packet_data);\r
+        return 1;\r
+    }\r
+\r
+    if (opus_frame_to_pcm_decode_packet(packet_data, packet_len, sample_rate, channels,\r
+                                        (short *)pcm, MAX_PCM_SAMPLES * channels, &pcm_samples) != 0) {\r
+        free(pcm);\r
+        free(packet_data);\r
+        return 1;\r
+    }\r
+\r
+    /* Open output file */\r
+    if (output_file) {\r
+        fout = fopen(output_file, "wb");\r
+        if (!fout) {\r
+            free(pcm);\r
+            free(packet_data);\r
+            return 1;\r
+        }\r
+    } else {\r
+        fout = stdout;\r
+    }\r
+\r
+    /* Write PCM data (16-bit little-endian bytes) */\r
+    for (int i = 0; i < pcm_samples; i++) {\r
+        uint16_t sample = (uint16_t)pcm[i];\r
+        uint8_t bytes[2] = { sample & 0xFF, (sample >> 8) & 0xFF };\r
+        if (fwrite(bytes, 1, 2, fout) != 2) {\r
+            if (fout != stdout) fclose(fout);\r
+            free(pcm);\r
+            free(packet_data);\r
+            return 1;\r
+        }\r
+    }\r
+\r
+    if (fout != stdout) {\r
+        fclose(fout);\r
+    }\r
+\r
+    free(pcm);\r
+    free(packet_data);\r
+    return 0;\r
+}\r
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/analysis.h b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/analysis.h
new file mode 100644 (file)
index 0000000..cb19cc0
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (c) 2011 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ANALYSIS_H
+#define ANALYSIS_H
+
+#include "celt.h"
+#include "opus_private.h"
+#include "mlp.h"
+
+#define NB_FRAMES 8
+#define NB_TBANDS 18
+#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
+
+/* At that point we can stop counting frames because it no longer matters. */
+#define ANALYSIS_COUNT_MAX 10000
+
+#define DETECT_SIZE 100
+
+/* Uncomment this to print the MLP features on stdout. */
+/*#define MLP_TRAINING*/
+
+typedef struct {
+   int arch;
+   int application;
+   opus_int32 Fs;
+#define TONALITY_ANALYSIS_RESET_START angle
+   float angle[240];
+   float d_angle[240];
+   float d2_angle[240];
+   opus_val32 inmem[ANALYSIS_BUF_SIZE];
+   int   mem_fill;                      /* number of usable samples in the buffer */
+   float prev_band_tonality[NB_TBANDS];
+   float prev_tonality;
+   int prev_bandwidth;
+   float E[NB_FRAMES][NB_TBANDS];
+   float logE[NB_FRAMES][NB_TBANDS];
+   float lowE[NB_TBANDS];
+   float highE[NB_TBANDS];
+   float meanE[NB_TBANDS+1];
+   float mem[32];
+   float cmean[8];
+   float std[9];
+   float Etracker;
+   float lowECount;
+   int E_count;
+   int count;
+   int analysis_offset;
+   int write_pos;
+   int read_pos;
+   int read_subframe;
+   float hp_ener_accum;
+   int initialized;
+   float rnn_state[MAX_NEURONS];
+   opus_val32 downmix_state[3];
+   AnalysisInfo info[DETECT_SIZE];
+} TonalityAnalysisState;
+
+/** Initialize a TonalityAnalysisState struct.
+ *
+ * This performs some possibly slow initialization steps which should
+ * not be repeated every analysis step. No allocated memory is retained
+ * by the state struct, so no cleanup call is required.
+ */
+void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
+
+/** Reset a TonalityAnalysisState struct.
+ *
+ * Call this when there's a discontinuity in the data.
+ */
+void tonality_analysis_reset(TonalityAnalysisState *analysis);
+
+void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
+
+void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
+                 int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
+                 int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
+
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/extensions.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/extensions.c
new file mode 100644 (file)
index 0000000..d505978
--- /dev/null
@@ -0,0 +1,672 @@
+/* Copyright (c) 2022 Amazon */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "arch.h"
+#include "os_support.h"
+#include "opus_private.h"
+
+
+/* Given an extension payload (i.e., excluding the initial ID byte), advance
+    data to the next extension and return the length of the remaining
+    extensions.
+   N.B., a "Repeat These Extensions" extension (ID==2) does not advance past
+    the repeated extension payloads.
+   That requires higher-level logic. */
+static opus_int32 skip_extension_payload(const unsigned char **pdata,
+ opus_int32 len, opus_int32 *pheader_size, int id_byte,
+ opus_int32 trailing_short_len)
+{
+   const unsigned char *data;
+   opus_int32 header_size;
+   int id, L;
+   data = *pdata;
+   header_size = 0;
+   id = id_byte>>1;
+   L = id_byte&1;
+   if ((id == 0 && L == 1) || id == 2)
+   {
+      /* Nothing to do. */
+   } else if (id > 0 && id < 32)
+   {
+      if (len < L)
+         return -1;
+      data += L;
+      len -= L;
+   } else {
+      if (L==0)
+      {
+         if (len < trailing_short_len) return -1;
+         data += len - trailing_short_len;
+         len = trailing_short_len;
+      } else {
+         opus_int32 bytes=0;
+         opus_int32 lacing;
+         do {
+            if (len < 1)
+               return -1;
+            lacing = *data++;
+            bytes += lacing;
+            header_size++;
+            len -= lacing + 1;
+         } while (lacing == 255);
+         if (len < 0)
+            return -1;
+         data += bytes;
+      }
+   }
+   *pdata = data;
+   *pheader_size = header_size;
+   return len;
+}
+
+/* Given an extension, advance data to the next extension and return the
+   length of the remaining extensions.
+   N.B., a "Repeat These Extensions" extension (ID==2) only advances past the
+    extension ID byte.
+   Higher-level logic is required to skip the extension payloads that come
+    after it.*/
+static opus_int32 skip_extension(const unsigned char **pdata, opus_int32 len,
+ opus_int32 *pheader_size)
+{
+   const unsigned char *data;
+   int id_byte;
+   if (len == 0) {
+      *pheader_size = 0;
+      return 0;
+   }
+   if (len < 1)
+      return -1;
+   data = *pdata;
+   id_byte = *data++;
+   len--;
+   len = skip_extension_payload(&data, len, pheader_size, id_byte, 0);
+   if (len >= 0) {
+      *pdata = data;
+      (*pheader_size)++;
+   }
+   return len;
+}
+
+void opus_extension_iterator_init(OpusExtensionIterator *iter,
+ const unsigned char *data, opus_int32 len, opus_int32 nb_frames) {
+   celt_assert(len >= 0);
+   celt_assert(data != NULL || len == 0);
+   celt_assert(nb_frames >= 0 && nb_frames <= 48);
+   iter->repeat_data = iter->curr_data = iter->data = data;
+   iter->last_long = iter->src_data = NULL;
+   iter->curr_len = iter->len = len;
+   iter->repeat_len = iter->src_len = 0;
+   iter->trailing_short_len = 0;
+   iter->frame_max = iter->nb_frames = nb_frames;
+   iter->repeat_frame = iter->curr_frame = 0;
+   iter->repeat_l = 0;
+}
+
+/* Reset the iterator so it can start iterating again from the first
+    extension. */
+void opus_extension_iterator_reset(OpusExtensionIterator *iter) {
+   iter->repeat_data = iter->curr_data = iter->data;
+   iter->last_long = NULL;
+   iter->curr_len = iter->len;
+   iter->repeat_frame = iter->curr_frame = 0;
+   iter->trailing_short_len = 0;
+}
+
+/* Tell the iterator not to return any extensions for frames of index
+    frame_max or larger.
+   This can allow it to stop iterating early if these extensions are not
+    needed. */
+void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
+ int frame_max) {
+   iter->frame_max = frame_max;
+}
+
+/* Return the next repeated extension.
+   The return value is non-zero if one is found, negative on error, or 0 if we
+    have finished repeating extensions. */
+static int opus_extension_iterator_next_repeat(OpusExtensionIterator *iter,
+ opus_extension_data *ext) {
+   opus_int32 header_size;
+   celt_assert(iter->repeat_frame > 0);
+   for (;iter->repeat_frame < iter->nb_frames; iter->repeat_frame++) {
+      while (iter->src_len > 0) {
+         const unsigned char *curr_data0;
+         int repeat_id_byte;
+         repeat_id_byte = *iter->src_data;
+         iter->src_len = skip_extension(&iter->src_data, iter->src_len,
+          &header_size);
+         /* We skipped this extension earlier, so it should not fail now. */
+         celt_assert(iter->src_len >= 0);
+         /* Don't repeat padding or frame separators with a 0 increment. */
+         if (repeat_id_byte <= 3) continue;
+         /* If the "Repeat These Extensions" extension had L == 0 and this
+             is the last repeated long extension, then force decoding the
+             payload with L = 0. */
+         if (iter->repeat_l == 0
+          && iter->repeat_frame + 1 >= iter->nb_frames
+          && iter->src_data == iter->last_long) {
+            repeat_id_byte &= ~1;
+         }
+         curr_data0 = iter->curr_data;
+         iter->curr_len = skip_extension_payload(&iter->curr_data,
+          iter->curr_len, &header_size, repeat_id_byte,
+          iter->trailing_short_len);
+         if (iter->curr_len < 0) {
+            return OPUS_INVALID_PACKET;
+         }
+         celt_assert(iter->curr_data - iter->data
+          == iter->len - iter->curr_len);
+         /* If we were asked to stop at frame_max, skip extensions for later
+             frames. */
+         if (iter->repeat_frame >= iter->frame_max) {
+            continue;
+         }
+         if (ext != NULL) {
+            ext->id = repeat_id_byte >> 1;
+            ext->frame = iter->repeat_frame;
+            ext->data = curr_data0 + header_size;
+            ext->len = iter->curr_data - curr_data0 - header_size;
+         }
+         return 1;
+      }
+      /* We finished repeating the extensions for this frame. */
+      iter->src_data = iter->repeat_data;
+      iter->src_len = iter->repeat_len;
+   }
+   /* We finished repeating extensions. */
+   iter->repeat_data = iter->curr_data;
+   iter->last_long = NULL;
+   /* If L == 0, advance the frame number to handle the case where we did
+       not consume all of the data with an L == 0 long extension. */
+   if (iter->repeat_l == 0) {
+      iter->curr_frame++;
+      /* Ignore additional padding if this was already the last frame. */
+      if (iter->curr_frame >= iter->nb_frames) {
+         iter->curr_len = 0;
+      }
+   }
+   iter->repeat_frame = 0;
+   return 0;
+}
+
+/* Return the next extension (excluding real padding, separators, and repeat
+    indicators, but including the repeated extensions) in bitstream order.
+   Due to the extension repetition mechanism, extensions are not necessarily
+    returned in frame order. */
+int opus_extension_iterator_next(OpusExtensionIterator *iter,
+ opus_extension_data *ext) {
+   opus_int32 header_size;
+   if (iter->curr_len < 0) {
+      return OPUS_INVALID_PACKET;
+   }
+   if (iter->repeat_frame > 0) {
+      int ret;
+      /* We are in the process of repeating some extensions. */
+      ret = opus_extension_iterator_next_repeat(iter, ext);
+      if (ret) return ret;
+   }
+   /* Checking this here allows opus_extension_iterator_set_frame_max() to be
+       called at any point. */
+   if (iter->curr_frame >= iter->frame_max) {
+      return 0;
+   }
+   while (iter->curr_len > 0) {
+      const unsigned char *curr_data0;
+      int id;
+      int L;
+      curr_data0 = iter->curr_data;
+      id = *curr_data0>>1;
+      L = *curr_data0&1;
+      iter->curr_len = skip_extension(&iter->curr_data, iter->curr_len,
+       &header_size);
+      if (iter->curr_len < 0) {
+         return OPUS_INVALID_PACKET;
+      }
+      celt_assert(iter->curr_data - iter->data == iter->len - iter->curr_len);
+      if (id == 1) {
+         if (L == 0) {
+            iter->curr_frame++;
+         }
+         else {
+            /* A frame increment of 0 is a no-op. */
+            if (!curr_data0[1]) continue;
+            iter->curr_frame += curr_data0[1];
+         }
+         if (iter->curr_frame >= iter->nb_frames) {
+            iter->curr_len = -1;
+            return OPUS_INVALID_PACKET;
+         }
+         /* If we were asked to stop at frame_max, skip extensions for later
+             frames. */
+         if (iter->curr_frame >= iter->frame_max) {
+            iter->curr_len = 0;
+         }
+         iter->repeat_data = iter->curr_data;
+         iter->last_long = NULL;
+         iter->trailing_short_len = 0;
+      }
+      else if (id == 2) {
+         int ret;
+         iter->repeat_l = L;
+         iter->repeat_frame = iter->curr_frame + 1;
+         iter->repeat_len = curr_data0 - iter->repeat_data;
+         iter->src_data = iter->repeat_data;
+         iter->src_len = iter->repeat_len;
+         ret = opus_extension_iterator_next_repeat(iter, ext);
+         if (ret) return ret;
+      }
+      else if (id > 2) {
+         /* Update the location of the last long extension.
+            This lets us know when we need to modify the last L flag if we
+             repeat these extensions with L=0. */
+         if (id >= 32) {
+           iter->last_long = iter->curr_data;
+           iter->trailing_short_len = 0;
+         }
+         /* Otherwise, keep track of how many payload bytes follow the last
+             long extension. */
+         else iter->trailing_short_len += L;
+         if (ext != NULL) {
+            ext->id = id;
+            ext->frame = iter->curr_frame;
+            ext->data = curr_data0 + header_size;
+            ext->len = iter->curr_data - curr_data0 - header_size;
+         }
+         return 1;
+      }
+   }
+   return 0;
+}
+
+int opus_extension_iterator_find(OpusExtensionIterator *iter,
+ opus_extension_data *ext, int id) {
+   opus_extension_data curr_ext;
+   int ret;
+   for(;;) {
+      ret = opus_extension_iterator_next(iter, &curr_ext);
+      if (ret <= 0) {
+         return ret;
+      }
+      if (curr_ext.id == id) {
+         *ext = curr_ext;
+         return ret;
+      }
+   }
+}
+
+/* Count the number of extensions, excluding real padding, separators, and
+    repeat indicators, but including the repeated extensions. */
+opus_int32 opus_packet_extensions_count(const unsigned char *data,
+ opus_int32 len, int nb_frames)
+{
+   OpusExtensionIterator iter;
+   int count;
+   opus_extension_iterator_init(&iter, data, len, nb_frames);
+   for (count=0; opus_extension_iterator_next(&iter, NULL) > 0; count++);
+   return count;
+}
+
+/* Count the number of extensions for each frame, excluding real padding and
+    separators and repeat indicators, but including the repeated extensions. */
+opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
+ opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames) {
+   OpusExtensionIterator iter;
+   opus_extension_data ext;
+   int count;
+   opus_extension_iterator_init(&iter, data, len, nb_frames);
+   OPUS_CLEAR(nb_frame_exts, nb_frames);
+   for (count=0; opus_extension_iterator_next(&iter, &ext) > 0; count++) {
+      nb_frame_exts[ext.frame]++;
+   }
+   return count;
+}
+
+/* Extract extensions from Opus padding (excluding real padding, separators,
+    and repeat indicators, but including the repeated extensions) in bitstream
+    order.
+   Due to the extension repetition mechanism, extensions are not necessarily
+    returned in frame order. */
+opus_int32 opus_packet_extensions_parse(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ int nb_frames) {
+   OpusExtensionIterator iter;
+   int count;
+   int ret;
+   celt_assert(nb_extensions != NULL);
+   celt_assert(extensions != NULL || *nb_extensions == 0);
+   opus_extension_iterator_init(&iter, data, len, nb_frames);
+   for (count=0;; count++) {
+      opus_extension_data ext;
+      ret = opus_extension_iterator_next(&iter, &ext);
+      if (ret <= 0) break;
+      if (count == *nb_extensions) {
+         return OPUS_BUFFER_TOO_SMALL;
+      }
+      extensions[count] = ext;
+   }
+   *nb_extensions = count;
+   return ret;
+}
+
+/* Extract extensions from Opus padding (excluding real padding, separators,
+    and repeat indicators, but including the repeated extensions) in frame
+    order.
+   nb_frame_exts must be filled with the output of
+    opus_packet_extensions_count_ext(). */
+opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ const opus_int32 *nb_frame_exts, int nb_frames) {
+   OpusExtensionIterator iter;
+   opus_extension_data ext;
+   opus_int32 nb_frames_cum[49];
+   int count;
+   int prev_total;
+   int ret;
+   celt_assert(nb_extensions != NULL);
+   celt_assert(extensions != NULL || *nb_extensions == 0);
+   celt_assert(nb_frames <= 48);
+   /* Convert the frame extension count array to a cumulative sum. */
+   prev_total = 0;
+   for (count=0; count<nb_frames; count++) {
+      int total;
+      total = nb_frame_exts[count] + prev_total;
+      nb_frames_cum[count] = prev_total;
+      prev_total = total;
+   }
+   nb_frames_cum[count] = prev_total;
+   opus_extension_iterator_init(&iter, data, len, nb_frames);
+   for (count=0;; count++) {
+      opus_int32 idx;
+      ret = opus_extension_iterator_next(&iter, &ext);
+      if (ret <= 0) break;
+      idx = nb_frames_cum[ext.frame]++;
+      if (idx >= *nb_extensions) {
+         return OPUS_BUFFER_TOO_SMALL;
+      }
+      celt_assert(idx < nb_frames_cum[ext.frame + 1]);
+      extensions[idx] = ext;
+   }
+   *nb_extensions = count;
+   return ret;
+}
+
+static int write_extension_payload(unsigned char *data, opus_int32 len,
+ opus_int32 pos, const opus_extension_data *ext, int last) {
+   celt_assert(ext->id >= 3 && ext->id <= 127);
+   if (ext->id < 32)
+   {
+      if (ext->len < 0 || ext->len > 1)
+         return OPUS_BAD_ARG;
+      if (ext->len > 0) {
+         if (len-pos < ext->len)
+            return OPUS_BUFFER_TOO_SMALL;
+         if (data) data[pos] = ext->data[0];
+         pos++;
+      }
+   } else {
+      opus_int32 length_bytes;
+      if (ext->len < 0)
+         return OPUS_BAD_ARG;
+      length_bytes = 1 + ext->len/255;
+      if (last)
+         length_bytes = 0;
+      if (len-pos < length_bytes + ext->len)
+         return OPUS_BUFFER_TOO_SMALL;
+      if (!last)
+      {
+         opus_int32 j;
+         for (j=0;j<ext->len/255;j++) {
+            if (data) data[pos] = 255;
+            pos++;
+         }
+         if (data) data[pos] = ext->len % 255;
+         pos++;
+      }
+      if (data) OPUS_COPY(&data[pos], ext->data, ext->len);
+      pos += ext->len;
+   }
+   return pos;
+}
+
+static int write_extension(unsigned char *data, opus_int32 len, opus_int32 pos,
+ const opus_extension_data *ext, int last) {
+   if (len-pos < 1)
+      return OPUS_BUFFER_TOO_SMALL;
+   celt_assert(ext->id >= 3 && ext->id <= 127);
+   if (data) data[pos] = (ext->id<<1) + (ext->id < 32 ? ext->len : !last);
+   pos++;
+   return write_extension_payload(data, len, pos, ext, last);
+}
+
+opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
+ const opus_extension_data  *extensions, opus_int32 nb_extensions,
+ int nb_frames, int pad)
+{
+   opus_int32 frame_min_idx[48];
+   opus_int32 frame_max_idx[48];
+   opus_int32 frame_repeat_idx[48];
+   opus_int32 i;
+   int f;
+   int curr_frame = 0;
+   opus_int32 pos = 0;
+   opus_int32 written = 0;
+
+   celt_assert(len >= 0);
+   if (nb_frames > 48) return OPUS_BAD_ARG;
+
+   /* Do a little work up-front to make this O(nb_extensions) instead of
+       O(nb_extensions*nb_frames) so long as the extensions are in frame
+       order (without requiring that they be in frame order). */
+   for (f=0;f<nb_frames;f++) frame_min_idx[f] = nb_extensions;
+   OPUS_CLEAR(frame_max_idx, nb_frames);
+   for (i=0;i<nb_extensions;i++)
+   {
+      f = extensions[i].frame;
+      if (f < 0 || f >= nb_frames) return OPUS_BAD_ARG;
+      if (extensions[i].id < 3 || extensions[i].id > 127) return OPUS_BAD_ARG;
+      frame_min_idx[f] = IMIN(frame_min_idx[f], i);
+      frame_max_idx[f] = IMAX(frame_max_idx[f], i+1);
+   }
+   for (f=0;f<nb_frames;f++) frame_repeat_idx[f] = frame_min_idx[f];
+   for (f=0;f<nb_frames;f++)
+   {
+      opus_int32 last_long_idx;
+      int repeat_count;
+      repeat_count = 0;
+      last_long_idx = -1;
+      if (f + 1 < nb_frames)
+      {
+         for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
+         {
+            if (extensions[i].frame == f)
+            {
+               int g;
+               /* Test if we can repeat this extension in future frames. */
+               for (g=f+1;g<nb_frames;g++)
+               {
+                  if (frame_repeat_idx[g] >= frame_max_idx[g]) break;
+                  celt_assert(extensions[frame_repeat_idx[g]].frame == g);
+                  if (extensions[frame_repeat_idx[g]].id != extensions[i].id)
+                  {
+                     break;
+                  }
+                  if (extensions[frame_repeat_idx[g]].id < 32
+                    && extensions[frame_repeat_idx[g]].len
+                    != extensions[i].len)
+                  {
+                     break;
+                  }
+               }
+               if (g < nb_frames) break;
+               /* We can! */
+               /* If this is a long extension, save the index of the last
+                   instance, so we can modify its L flag. */
+               if (extensions[i].id >= 32) {
+                  last_long_idx = frame_repeat_idx[nb_frames-1];
+               }
+               /* Using the repeat mechanism almost always makes the
+                   encoding smaller (or at least no larger).
+                  However, there's one case where that might not be true: if
+                   the last repeated long extension in the last frame was
+                   previously the last extension, but using the repeat
+                   mechanism makes that no longer true (because there are other
+                   non-repeated extensions in earlier frames that must now be
+                   coded after it), and coding its length requires more bytes
+                   than the repeat mechanism saves.
+                  This can only be true if its length is at least 255 bytes
+                   (although sometimes it requires even more).
+                  Currently we do not check for that, and just always use the
+                   repeat mechanism if we can.
+                  See git history for code that does the check. */
+               /* Advance the repeat pointers. */
+               for (g=f+1; g<nb_frames; g++)
+               {
+                  int j;
+                  for (j=frame_repeat_idx[g]+1; j<frame_max_idx[g]
+                   && extensions[j].frame != g; j++);
+                  frame_repeat_idx[g] = j;
+               }
+               repeat_count++;
+               /* Point the repeat pointer for this frame to the current
+                   extension, so we know when to trigger the repeats. */
+               frame_repeat_idx[f] = i;
+            }
+         }
+      }
+      for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
+      {
+         if (extensions[i].frame == f)
+         {
+            /* Insert separator when needed. */
+            if (f != curr_frame) {
+               int diff = f - curr_frame;
+               if (len-pos < 2)
+                  return OPUS_BUFFER_TOO_SMALL;
+               if (diff == 1) {
+                  if (data) data[pos] = 0x02;
+                  pos++;
+               } else {
+                  if (data) data[pos] = 0x03;
+                  pos++;
+                  if (data) data[pos] = diff;
+                  pos++;
+               }
+               curr_frame = f;
+            }
+
+            pos = write_extension(data, len, pos, extensions + i,
+             written == nb_extensions - 1);
+            if (pos < 0) return pos;
+            written++;
+
+            if (repeat_count > 0 && frame_repeat_idx[f] == i) {
+               int nb_repeated;
+               int last;
+               int g;
+               /* Add the repeat indicator. */
+               nb_repeated = repeat_count*(nb_frames - (f + 1));
+               last = written + nb_repeated == nb_extensions
+                || (last_long_idx < 0 && i+1 >= frame_max_idx[f]);
+               if (len-pos < 1)
+                  return OPUS_BUFFER_TOO_SMALL;
+               if (data) data[pos] = 0x04 + !last;
+               pos++;
+               for (g=f+1;g<nb_frames;g++)
+               {
+                  int j;
+                  for (j=frame_min_idx[g];j<frame_repeat_idx[g];j++)
+                  {
+                     if (extensions[j].frame == g)
+                     {
+                        pos = write_extension_payload(data, len, pos,
+                         extensions + j, last && j == last_long_idx);
+                        if (pos < 0) return pos;
+                        written++;
+                     }
+                  }
+                  frame_min_idx[g] = j;
+               }
+               if (last) curr_frame++;
+            }
+         }
+      }
+   }
+   celt_assert(written == nb_extensions);
+   /* If we need to pad, just prepend 0x01 bytes. Even better would be to fill the
+      end with zeros, but that requires checking that turning the last extension into
+      an L=1 case still fits. */
+   if (pad && pos < len)
+   {
+      opus_int32 padding = len - pos;
+      if (data) {
+         OPUS_MOVE(data+padding, data, pos);
+         for (i=0;i<padding;i++)
+            data[i] = 0x01;
+      }
+      pos += padding;
+   }
+   return pos;
+}
+
+#if 0
+#include <stdio.h>
+int main()
+{
+   opus_extension_data ext[] = {{2, 0, (const unsigned char *)"a", 1},
+   {32, 10, (const unsigned char *)"DRED", 4},
+   {33, 1, (const unsigned char *)"NOT DRED", 8},
+   {3, 4, (const unsigned char *)NULL, 0}
+   };
+   opus_extension_data ext2[10];
+   int i, len;
+   int nb_ext = 10;
+   unsigned char packet[10000];
+   len = opus_packet_extensions_generate(packet, 32, ext, 4, 1);
+   for (i=0;i<len;i++)
+   {
+      printf("%#04x ", packet[i]);
+      if (i%16 == 15)
+         printf("\n");
+   }
+   printf("\n");
+   printf("count = %d\n", opus_packet_extensions_count(packet, len));
+   opus_packet_extensions_parse(packet, len, ext2, &nb_ext);
+   for (i=0;i<nb_ext;i++)
+   {
+      int j;
+      printf("%d %d {", ext2[i].id, ext2[i].frame);
+      for (j=0;j<ext2[i].len;j++) printf("%#04x ", ext2[i].data[j]);
+      printf("} %d\n", ext2[i].len);
+   }
+}
+#endif
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.c
new file mode 100644 (file)
index 0000000..6a68100
--- /dev/null
@@ -0,0 +1,997 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arch.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "mapping_matrix.h"
+
+#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
+
+opus_int32 mapping_matrix_get_size(int rows, int cols)
+{
+  opus_int32 size;
+
+  /* Mapping Matrix must only support up to 255 channels in or out.
+   * Additionally, the total cell count must be <= 65004 octets in order
+   * for the matrix to be stored in an OGG header.
+   */
+  if (rows > 255 || cols > 255)
+      return 0;
+  size = rows * (opus_int32)cols * sizeof(opus_int16);
+  if (size > 65004)
+    return 0;
+
+  return align(sizeof(MappingMatrix)) + align(size);
+}
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
+{
+  /* void* cast avoids clang -Wcast-align warning */
+  return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
+}
+
+void mapping_matrix_init(MappingMatrix * const matrix,
+  int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
+{
+  int i;
+  opus_int16 *ptr;
+
+#if !defined(ENABLE_ASSERTIONS)
+  (void)data_size;
+#endif
+  celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
+
+  matrix->rows = rows;
+  matrix->cols = cols;
+  matrix->gain = gain;
+  ptr = mapping_matrix_get_data(matrix);
+  for (i = 0; i < rows * cols; i++)
+  {
+     ptr[i] = data[i];
+  }
+}
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+    const MappingMatrix *matrix,
+    const float *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, col;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    float tmp = 0;
+    for (col = 0; col < input_rows; col++)
+    {
+      tmp +=
+        matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        input[MATRIX_INDEX(input_rows, col, i)];
+    }
+    output[output_rows * i] = FLOAT2RES((1/32768.f)*tmp);
+  }
+}
+
+void mapping_matrix_multiply_channel_out_float(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    float *output,
+    int output_rows,
+    int frame_size
+)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, row;
+  float input_sample;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    input_sample = RES2FLOAT(input[input_rows * i]);
+    for (row = 0; row < output_rows; row++)
+    {
+      float tmp =
+        (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+        input_sample;
+      output[MATRIX_INDEX(output_rows, row, i)] += tmp;
+    }
+  }
+}
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+    const MappingMatrix *matrix,
+    const opus_int16 *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, col;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    opus_val32 tmp = 0;
+    for (col = 0; col < input_rows; col++)
+    {
+#if defined(FIXED_POINT)
+      tmp +=
+        ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
+#else
+      tmp +=
+        matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        input[MATRIX_INDEX(input_rows, col, i)];
+#endif
+    }
+#if defined(FIXED_POINT)
+#ifdef ENABLE_RES24
+    output[output_rows * i] = SHL32(tmp, RES_SHIFT-7);
+#else
+    output[output_rows * i] = SATURATE16((tmp + 64) >> 7);
+#endif
+#else
+    output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
+#endif
+  }
+}
+
+void mapping_matrix_multiply_channel_out_short(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    opus_int16 *output,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, row;
+  opus_int32 input_sample;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    input_sample = RES2INT16(input[input_rows * i]);
+    for (row = 0; row < output_rows; row++)
+    {
+      opus_int32 tmp =
+        (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+        input_sample;
+      output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+    }
+  }
+}
+
+void mapping_matrix_multiply_channel_in_int24(
+    const MappingMatrix *matrix,
+    const opus_int32 *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, col;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    opus_val64 tmp = 0;
+    for (col = 0; col < input_rows; col++)
+    {
+      tmp +=
+        matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        (opus_val64)input[MATRIX_INDEX(input_rows, col, i)];
+    }
+#if defined(FIXED_POINT)
+    output[output_rows * i] = INT24TORES((tmp + 16384) >> 15);
+#else
+    output[output_rows * i] = INT24TORES((1/(32768.f))*tmp);
+#endif
+  }
+}
+
+void mapping_matrix_multiply_channel_out_int24(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    opus_int32 *output,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, row;
+  opus_int32 input_sample;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    input_sample = RES2INT24(input[input_rows * i]);
+    for (row = 0; row < output_rows; row++)
+    {
+      opus_int64 tmp =
+        (opus_int64)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+        input_sample;
+      output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+    }
+  }
+}
+
+
+const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_mixing_data[36] = {
+     16384,      0, -16384,  23170,      0,      0,  16384,  23170,
+     16384,      0,      0,      0,  16384,      0, -16384, -23170,
+         0,      0,  16384, -23170,  16384,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
+const opus_int16 mapping_matrix_soa_mixing_data[121] = {
+     10923,   7723,  13377, -13377,  11585,   9459,   7723, -16384,
+     -6689,      0,      0,  10923,   7723,  13377,  13377, -11585,
+      9459,   7723,  16384,  -6689,      0,      0,  10923, -15447,
+     13377,      0,      0, -18919,   7723,      0,  13377,      0,
+         0,  10923,   7723, -13377, -13377,  11585,  -9459,   7723,
+     16384,  -6689,      0,      0,  10923,  -7723,      0,  13377,
+    -16384,      0, -15447,      0,   9459,      0,      0,  10923,
+     -7723,      0, -13377,  16384,      0, -15447,      0,   9459,
+         0,      0,  10923,  15447,      0,      0,      0,      0,
+    -15447,      0, -18919,      0,      0,  10923,   7723, -13377,
+     13377, -11585,  -9459,   7723, -16384,  -6689,      0,      0,
+     10923, -15447, -13377,      0,      0,  18919,   7723,      0,
+     13377,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767
+};
+
+const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_mixing_data[324] = {
+      8208,      0,   -881,  14369,      0,      0,  -8192,  -4163,
+     13218,      0,      0,      0,  11095,  -8836,  -6218,  14833,
+         0,      0,   8208, -10161,    881,  10161, -13218,  -2944,
+     -8192,   2944,      0, -10488,  -6218,   6248, -11095,  -6248,
+         0, -10488,      0,      0,   8208,  10161,    881, -10161,
+    -13218,   2944,  -8192,  -2944,      0,  10488,  -6218,  -6248,
+    -11095,   6248,      0,  10488,      0,      0,   8176,   5566,
+    -11552,   5566,   9681, -11205,   8192, -11205,      0,   4920,
+    -15158,   9756,  -3334,   9756,      0,  -4920,      0,      0,
+      8176,   7871,  11552,      0,      0,  15846,   8192,      0,
+     -9681,  -6958,      0,  13797,   3334,      0, -15158,      0,
+         0,      0,   8176,      0,  11552,   7871,      0,      0,
+      8192,  15846,   9681,      0,      0,      0,   3334,  13797,
+     15158,   6958,      0,      0,   8176,   5566, -11552,  -5566,
+     -9681, -11205,   8192,  11205,      0,   4920,  15158,   9756,
+     -3334,  -9756,      0,   4920,      0,      0,   8208,  14369,
+      -881,      0,      0,  -4163,  -8192,      0, -13218, -14833,
+         0,  -8836,  11095,      0,   6218,      0,      0,      0,
+      8208,  10161,    881,  10161,  13218,   2944,  -8192,   2944,
+         0,  10488,   6218,  -6248, -11095,  -6248,      0, -10488,
+         0,      0,   8208, -14369,   -881,      0,      0,   4163,
+     -8192,      0, -13218,  14833,      0,   8836,  11095,      0,
+      6218,      0,      0,      0,   8208,      0,   -881, -14369,
+         0,      0,  -8192,   4163,  13218,      0,      0,      0,
+     11095,   8836,  -6218, -14833,      0,      0,   8176,  -5566,
+    -11552,   5566,  -9681,  11205,   8192, -11205,      0,  -4920,
+     15158,  -9756,  -3334,   9756,      0,  -4920,      0,      0,
+      8176,      0,  11552,  -7871,      0,      0,   8192, -15846,
+      9681,      0,      0,      0,   3334, -13797,  15158,  -6958,
+         0,      0,   8176,  -7871,  11552,      0,      0, -15846,
+      8192,      0,  -9681,   6958,      0, -13797,   3334,      0,
+    -15158,      0,      0,      0,   8176,  -5566, -11552,  -5566,
+      9681,  11205,   8192,  11205,      0,  -4920, -15158,  -9756,
+     -3334,  -9756,      0,   4920,      0,      0,   8208, -10161,
+       881, -10161,  13218,  -2944,  -8192,  -2944,      0, -10488,
+      6218,   6248, -11095,   6248,      0,  10488,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_fourthoa_mixing = { 27, 27, 0 };
+const opus_int16 mapping_matrix_fourthoa_mixing_data[729] = {
+      9243,      0,  16010,      0,      0,      0,  20669,      0,
+         0,      0,      0,      0,  24456,      0,      0,      0,
+         0,      0,      0,      0,  27731,      0,      0,      0,
+         0,      0,      0,   9243,      0,  10884,  11741,      0,
+         0,   3995,  17849,   9626,      0,      0,      0,  -5727,
+     14399,  17315,   7625,      0,      0,      0,      0, -11747,
+      2574,  18637,  15552,   5930,      0,      0,   9243, -14302,
+     -2682,  -6677,  13337,   5357,  -9464,   2501, -11170,   4770,
+     -5911,  11501,   5858,   5369,   4951,  17901, -19071,  -2397,
+     -9281,  -9198,   7576,  -4294,   7773,  -8997,  -3399,      0,
+         0,   9243,   9940,  11991,  -3705,  -5144,  16647,   7057,
+     -6206,  -5941,  -2698, -10194,  16781,  -1788,  -6256, -11772,
+      4935,   3912,  -6062, -13039,   9446,  -9758,  -3521, -15058,
+     11089,    565,      0,      0,   9243, -15376,   3720,   2461,
+     -5285,  -7989,  -8660,   1278, -16087,  15811,  -3249,  10500,
+     -7757,  -1680,  -9890,  -8153,  10884,  11022,   2847,  12828,
+      5137,  -2053,   8666,  -5684,  14776,      0,      0,   9243,
+    -10577,  10304,  -6186,   9139, -15222,   2507,  -8902,  -5140,
+      -145,  15562, -10596,  -7311,  -6197,  -8753,   8667,  -6014,
+      -281,  15033,    938, -11859,    548,  -8456,  16735,  -3654,
+         0,      0,   9243,   8974,   4839, -12343, -15472,   6066,
+     -7501,  -8343,   5015,  15920, -12374,  -4559,  -9400,   6271,
+      4011,   5191,  -9932,  14438,   4828,  -8768,   1909,  12059,
+     -1565,   4707, -13711,      0,      0,   9243,  15799,   2085,
+     -1534,  -3386,   4602,  -9808,   -447, -17267, -18054,  -1167,
+    -13525,  -4644,   1313,  -5951,   5397,   7485,  -7056,   2584,
+     -8120,   8669,    788,  13177,   2109,  18349,      0,      0,
+      9243,  12371, -10036,   1597,   2760, -17341,   1848,  -2239,
+    -10509,  -8474,  -4577,  11164,   7935,   1441,  17430,  -3436,
+     -3713,  15936,   4184,   2647, -11730,    341, -15934,   6462,
+      6581,      0,      0,   9243,  -8963,   2184,  13084, -16381,
+     -2734,  -9757,   3991,   6345, -18297,  -5912,   7604,  -4849,
+    -11100,   2290,  -4304, -13305,  -7488,  12338,   4805,   8505,
+     -7014,  -4779,  -1761, -14597,      0,      0,   9243,   1301,
+    -15498,   3799,    690,  -2816,  18718,  -8223,    889,    255,
+     -1768,   4485, -19951,  13097,  -2278,    167,     78,   -740,
+      3324,  -6139,  19488, -17925,   4283,   -486,     20,      0,
+         0,   9243, -13470,  -6719,   5452, -10257,  12641,  -4873,
+     -5116, -10595,   5856,  11389,   1502,  10876,   -608,  11765,
+    -13218,  13911,  -7373,  -2070, -13679,  -4154,   5536,  -2138,
+     16643,    451,      0,      0,   9243,   2455,  -3679, -15387,
+     -5277,  -1261,  -8697,   7906,  16112,   8147,   3208,  -1690,
+      7687,  10593,  -9796, -15852, -10884,  -5616,   2881,   2032,
+      5246, -12735,  -8796,  10928,  14833,      0,      0,   9243,
+     -6849,   2775, -14202,  13586,  -2655,  -9402,  -5505,  10809,
+    -18013,   6231,   5444,  -6041,  11288,   4958,  -4078,  18799,
+     -9368,  -9291,   4535,   7383,   9405,  -7391,  -2121,  -4336,
+         0,      0,   9243,   6423,  -9040,  11548,  10359,  -8109,
+      -450, -14580,   6431,  10857, -15475,   3569,   9707,   6416,
+     -9607,    521,   8528, -18391,  11049,   3815, -10423,   6860,
+      6860,   -883,  -4221,      0,      0,   9243,  11932,  -5968,
+     -8850, -14749,  -9946,  -6026,   7377,  -4472,   5206,  14547,
+     -3406,  10508,   2526,   4411,  14543,   8444,  -5822,    347,
+     12347,  -1709,  -9158,    105, -16265, -12642,      0,      0,
+      9243,  13044,   -150,   9282,  16910,   -274, -10332,   -194,
+     -5864,   5428,   -420, -12196,    344,  -8679,    145, -18554,
+    -12695,   -152, -14635,    503,  10389,    358,   5076,    522,
+    -16100,      0,      0,   9243,  -8374, -13590,  -1221,   1428,
+     15896,  12005,   2318,  -4793,   2590,  -3209, -20390,  -6256,
+     -2974,  10766,   1202,   -876,  -6597,   5004,  19896,  -1541,
+      2902, -16788,  -3062,   1340,      0,      0,   9243,   9879,
+     10267,   7300,  10073,  14167,   2416,  10469,  -3094,   2899,
+     17092,   9762,  -7400,   7214,  -5250,  -8238,  -3989,   5578,
+     16392,  -1050, -11848,   -776,  -5034, -15850,  -5882,      0,
+         0,   9243,  -4974,  -9068,  12221,  -8490,   6299,   -388,
+    -15478,   8702,  -9920,  12723,  -2810,   9668,   6905, -13040,
+      4325,  -9456,  16856,  -9159,  -2909, -10476,   7149,   9387,
+     -7350,    233,      0,      0,   9243,   3627, -13823,  -7218,
+     -3656,  -7002,  12776,  13935,   2719,   2446,   8352,   9252,
+     -7676, -18413,  -6212,   -429,  -1272,  -6335, -13356,  -9510,
+       295,  18926,   9934,   1112,   -382,      0,      0,   9243,
+     -6383,  -9343, -11326,  10097,   8329,    223,  14780,   6114,
+    -10348, -15590,  -4195,   9257,  -7445,  -9439,   -323,   7902,
+     18117,  12101,  -3142, -10944,  -5577,   7327,    566,  -4133,
+         0,      0,   9243,   2626,    865,  15769,   5783,    317,
+    -10244,   1905,  16884,   9144,    826,  -2420,  -1972, -14536,
+      2413,  16939,  12500,   1482,  -4906,   -578,  10096,  -3476,
+    -14323,   2745,  16105,      0,      0,   9243,  -8975,  12086,
+      5450,  -6832, -15149,   7333,   9200,  -3550,   -362, -13645,
+    -15525,  -1391,   9428,  -7091,  -5442,   3105,   -820, -17685,
+     -9175,  -9462,   5572,  -9191, -12325,  -2180,      0,      0,
+      9243,   -114,  11576, -11058,    177,   -185,   5875, -17880,
+      8539,   -198,    339,   -173,  -3411, -16698,  16336,  -6369,
+       193,   -430,    408,    -75, -10806,  -7225,  19670, -13817,
+      4665,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767
+};
+
+const MappingMatrix mapping_matrix_fifthoa_mixing = { 38, 38, 0 };
+const opus_int16 mapping_matrix_fifthoa_mixing_data[1444] = {
+      9243,      0,  16010,      0,      0,      0,  20669,      0,
+         0,      0,      0,      0,  24456,      0,      0,      0,
+         0,      0,      0,      0,  27731,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,  30657,      0,
+         0,      0,      0,      0,      0,      0,   9243,      0,
+     -7023,  14387,      0,      0,  -4369, -14112,  14455,      0,
+         0,      0,  10931,   -510, -16777,  14031,      0,      0,
+         0,      0,  -5118,  14286,   4343, -18465,  13374,      0,
+         0,      0,      0,      0,  -6494, -12221,  11761,   8513,
+    -19458,  12605,      0,      0,   9243, -14128,   5093,   5547,
+    -10946, -10050,  -7197,   3945, -11790,   7142,  -9213,   6529,
+     -9701,  -2563,  -9923, -14846,  16521,   6816,   2764,  14103,
+      1118,  -5537,   2977, -14168,   1228,   4866,  17430,   -528,
+     10639,   2641,  10437,  -1037,  11460,   1098,   1296,  15737,
+         0,      0,   9243,   1128, -14775,   6062,    955,  -2329,
+     16069, -12511,   2477,    579,  -2333,   3440, -14197,  18478,
+     -6050,    940,    303,  -1604,   4106,  -4223,   9829, -22688,
+     10647,  -2604,    334,    145,   -927,   3203,  -6017,   4507,
+     -3812,  24212, -15600,   5198,  -1023,    110,      0,      0,
+      9243,   1158,  12997,   9277,   1501,   2103,  10097,  16840,
+      5916,   1402,   3225,   2488,   2929,  19916,  12706,   3585,
+      1137,   3415,   4698,   2078,  -5442,  16634,  18511,   8731,
+      2095,    850,   3061,   5733,   5225,    960, -11728,   7689,
+     20588,  14659,   5642,   1187,      0,      0,   9243,  -4663,
+     -3081, -15003,   9771,   2007,  -9185,   6457,  14199, -14357,
+     -4976,   3554,   6625,  11434,  -7231, -11297,  17760,   8291,
+     -6267,  -3368,   6712, -10837,  -9107,   6524,   6793, -19531,
+    -11338,   7934,   7335,  -2205,  -9215,  -7094,  10659,   6243,
+     -4337,  -1250,      0,      0,   9243, -13515,   7679,  -3831,
+      7232, -14496,  -3201,  -4109, -11731,   8828,   9178,  -1901,
+    -10848,   -539, -14888,   9626, -10860,  12703,   3824,  12334,
+     -7104,   3496,  -6203,  13852,   5461,  -2109, -17277,   7837,
+     -4714,  13901,   4097,   3940,   7647,   8546,   8688, -10986,
+         0,      0,   9243,   8113,  -9860,   9657,  10943, -11174,
+      1426, -13300,   1915,   8178, -17833,   6805,   8309,   8100,
+     -3121,  -4742,   2683, -15111,  15688,   2358, -11590,   2807,
+      2746,   8762,  -7430,  -2251,  -5481,  16370,  -4081,  -9694,
+      5872, -11539,   -714,  -9492,  15177,  -6126,      0,      0,
+      9243,   9933,  -9215,  -8528, -11831, -12785,    -62,  10976,
+     -1811,   5593,  18018,   6100,   9455,  -5237,   2758,   8971,
+      2743,  -9659, -13517,   5330, -10737,  -4576,  -2069, -15491,
+     -8749,  -7226,  -5237,   9191,   -181, -12277,   2815,  10540,
+       -27,  14741,  16703,   3103,      0,      0,   9243, -10067,
+     -8881,  -8723,  12265,  12487,   -793,  10821,  -1762,  -6021,
+    -18002,  -5072,   9912,  -4395,   2587,   9368,  -2767,  10021,
+     12259,  -6468, -10113,  -5605,  -1761, -15590,  -9430,   7800,
+      5092,  -8835,   2293,  12314,   1222,  10671,   -329,  13745,
+     17349,   3563,      0,      0,   9243,  -6485,  12991,  -6743,
+      6108, -11768,  10080, -12236,    238,  -2883,  13115, -13907,
+      2900, -14460,    511,   2564,    186,  -7019,  19094, -11597,
+     -5472, -12058,    744,   6243,  -2384,    930,    501, -11778,
+     21214,  -5330, -11746,  -5542,    827,  10475,  -6418,   1132,
+         0,      0,   9243,   3862,   5238, -14627,  -7891,   2826,
+     -7015, -10701,  13900,  11410,  -6831,  -1679,  -9861,   6359,
+     12032, -11660, -14041,  11199,   1713,  -3895,    657,  14749,
+     -3017, -11445,   8380,  15575, -15236,   -346,   7690,   -923,
+     10317,   3498, -13545,    354,   9093,  -4476,      0,      0,
+      9243,  -8417,  13183,   3418,  -4018, -15498,  10685,   6294,
+     -4132,   1419,  -8755, -18818,   3926,   7642,  -9001,  -3235,
+      2125,   3506, -13037, -16570,  -4337,   6729, -13404,  -7991,
+        59,    443,   5804,   6005, -15011,  -9060, -11044,   3679,
+    -15434, -13685,    161,   1185,      0,      0,   9243,  -5288,
+      6773, -13508,   9977,  -5002,  -4784, -12780,  10790, -12942,
+     11168,    519, -10890,   1326,  12078,  -6274,  13780, -16427,
+      2186,   5352,  -4328,  13671,   2364,  -7963,   1080, -12568,
+     19336,  -6557,  -8574,   4084,   7277,  10433,  -9273,  -3178,
+      1516,   3817,      0,      0,   9243,   9660,   7817,  10093,
+     13619,  10548,  -2942,  11021,    597,   9663,  17594,   1736,
+    -10794,   1814,    771,  -8469,   1041,  14155,   7891,  -8597,
+     -7498,  -8982,    346, -12407, -11848,  -6809,   1686,   9181,
+     -8306, -10247,   3538, -10706,   -364,  -8047, -19188,  -8493,
+         0,      0,   9243,  -7163,  -1020,  14282, -14289,   1021,
+    -10208,  -2036,  10660, -18919,   2410,   6564,   2323, -13088,
+     -1798,   3365, -19498,   3619,  12022,  -1858,   9978,   3705,
+     -8969,   -643,  -5794, -15523,   4123,  15113,  -3949,  -6265,
+     -3596,  12490,   2946,  -2688,   1225, -14570,      0,      0,
+      9243, -12187,    772, -10354,  17623,  -1314, -10262,  -1117,
+     -2885,  -9937,   2249,  11267,  -1763,   9572,   -368,  16506,
+     -6510,  -1438, -15014,   2402,  10157,   2041,   2458,   2389,
+    -19346,  19860,  -1041,   8067,  -3704, -10931,   2743,  -9286,
+       606, -13399,  -3095,   7924,      0,      0,   9243,  15545,
+     -2367,  -3011,  -6538,  -5139,  -9657,    995, -16242, -15706,
+      2557, -12952,   5226,   2508,   6353,  10156,  13593,   6966,
+      4795,   8960,   8183,  -1735,  11914,  -4504,  14149,  11727,
+     -6665,  10460,  -3962,  10145,  -7648,  -1965,  -9845,  -6764,
+     -6938, -16633,      0,      0,   9243,   3098,  12983,  -8841,
+     -3826,   5618,  10053, -16031,   4787,   3283,  -8209,   6632,
+      2856, -18922,  10272,  -2055,  -2344,   7987, -11939,   5516,
+     -5520, -15739,  14940,  -5001,    530,   1465,  -6306,  13388,
+    -13243,   2513, -11772,  -7170,  16572,  -8384,   1426,    168,
+         0,      0,   9243, -15767,  -2008,  -1916,   4220,   4422,
+     -9846,    537, -17105,  17650,  -1400,  13589,   4481,   1651,
+      5677,   6701,  -9241,  -6642,  -3252,  -7827,   8792,   -951,
+     13182,  -2522,  17586, -17005,   3845, -12562,   2213, -11472,
+     -6688,  -1394,  -8970,  -4769,  -7316, -11753,      0,      0,
+      9243, -13344,  -3829,   7975, -14863,   7136,  -8561,  -4265,
+     -7992,   -801,   9405,   8912,   7937,  -5326,   5057, -17681,
+     15207,    575,   7717, -11360,   4847,   6789,   4150,  12686,
+    -10050,  16730, -12063,    322, -12920,  -3313, -10267,   1980,
+     -6948,   7112,   7972,   8042,      0,      0,   9243,   7791,
+     -1021,  13949,  15180,  -1111, -10208,  -1989,   9348,  19199,
+     -2561,  -7140,   2323, -12782,  -1577,    817,  18164,  -3673,
+    -12771,   2022,   9978,   3620,  -7865,   -156,  -9155,  11924,
+     -3842, -15336,   4196,   6814,  -3596,  12199,   2583,   -652,
+      1936, -17637,      0,      0,   9243,  -4810, -15144,  -1958,
+      1315,  10175,  17406,   4142,  -1348,    263,  -3292, -15632,
+    -17046,  -6363,   3374,    605,   -227,   -748,   5997,  20334,
+     14481,   8277,  -6146,  -1717,      5,     27,    712,   1542,
+     -9197, -23572, -10163,  -9595,   9425,   3539,    -17,    -72,
+         0,      0,   9243,  -7366,   8261,  11568, -11901,  -8499,
+     -2079,  13347,   5556, -12049, -16247,  -2282, -10529,   3584,
+      7585,  -1577,  -8464, -18652,  -8902,   5913,  -8688,  -9287,
+      4156,  -2442,  -7089,  -2993, -14485, -13949,   5422,   8459,
+      1638, -13285,  -2531,  -1826, -12132,  -9456,      0,      0,
+      9243,  11716,    698, -10889, -17818,   1143, -10275,  -1062,
+     -1305,  12057,  -2057, -10855,  -1595,  10088,   -150,  15043,
+      2978,   1578,  15225,  -2090,  10201,   1943,   1115,   1969,
+    -20211, -17636,    430,  -9826,   3391,  10572,   2485,  -9826,
+       248, -12259,  -2924,  12131,      0,      0,   9243,   4361,
+     -4594, -14703,  -8956,  -2798,  -7781,   9434,  13769,  12936,
+      6800,  -2400,   9082,   8091, -10453, -11023, -15786, -11136,
+      3285,   4153,   2658, -14002,  -5051,   9489,   7000,  17206,
+     15024,  -2777,  -8491,    -42, -10626,    141,  13053,   2366,
+     -6662,  -2231,      0,      0,   9243,   -752, -11933, -10646,
+      1119,   1254,   6890,  17745,   7875,  -1203,  -2207,  -1251,
+      2024, -17706, -15532,  -5600,   1128,   2691,   2800,    683,
+     -9927,   9661,  19706,  12522,   3889,   -978,  -2789,  -3992,
+     -2440,    206,  12695,   2921, -17173, -18575,  -9616,  -2657,
+         0,      0,   9243,   4791, -15001,  -2887,  -1931, -10037,
+     16885,   6048,  -1020,     46,   4789,  15191, -15922,  -9154,
+      2530,    823,    252,   -130,  -8608, -19335,  12613,  11651,
+     -4549,  -2314,   -172,   -101,   -784,    265,  12975,  21741,
+     -7551, -13101,   6856,   4710,    535,    -46,      0,      0,
+      9243, -12153, -10395,    754,  -1281,  17644,   2735,  -1095,
+    -10274,   8359,   2200, -12593,   7083,    782,  17650,  -1573,
+      1685, -16282,  -2164,   -530, -11878,     32, -17359,   3065,
+      6651,  -5212,  -3628,  19365,    965,  13180,   8243,   -818,
+      7746,  -3645, -14323,   1670,      0,      0,   9243,  -6961,
+    -11198,   9081,  -8829,  10887,   4833, -14202,   2374,  -6524,
+     16339,  -9417,   4737,  12284,  -4394,  -2691,  -2683,  13690,
+    -18539,   2830, -11438,  -3692,   4985,   5648,  -4628,    514,
+      6225, -18409,  12672,   5311,  11170,  -6928,  -3407,  -7595,
+     10737,  -3977,      0,      0,   9243,  12099, -10405,   1294,
+      2187, -17582,   2760,  -1880, -10105,  -8058,  -3760,  12583,
+      7058,   1346,  17376,  -2667,  -2829,  15710,   3705,    468,
+    -11880,     50, -17123,   5201,   6230,   4698,   6098, -18716,
+     -1665, -13088,   8285,  -1400,   7696,  -6196, -13429,   2770,
+         0,      0,   9243,   8602,  13392,   1722,   2070,  16090,
+     11359,   3222,  -4960,  -2638,   4581,  20106,   5099,   4026,
+    -10978,  -1778,  -1314,  -6620,   6988,  18701,  -2965,   3745,
+    -16745,  -4461,   1300,    584,  -3646, -11588,   8350,  11847,
+    -10050,   2372, -20010,  -7809,   3608,    887,      0,      0,
+      9243,  14252,  -1958,   7026,  13986,  -3899,  -9870,  -1922,
+    -10736,  -3693,  -4527, -12333,   4376,  -6080,   3475, -18537,
+    -19222,   1355, -10843,   6913,   8869,   3408,   8323,   6804,
+     -5141, -13648,   7800,   2649,   7171,  10505,  -6548,   5179,
+     -5505,  13299,   2086,  15579,      0,      0,   9243,  11323,
+      9021,  -6835, -10810,  14267,   -489,  -8613,  -5689,    639,
+    -16117,   6224,  -9731,  -3757,  -8482,  10882,   7873,   1080,
+    -11447,  -6791, -10388,   4099,  -6025,  18396,  -5407,  -7536,
+     14714,    984,   1267, -13940,  -1889,   8416,    666,  16762,
+    -10106,  -3418,      0,      0,   9243,    871,   4833,  15238,
+      1855,    588,  -7508,  10287,  16162,   2857,   1481,   -443,
+     -9392,  -7758,  12910,  16506,   3837,   2588,   -581,   -851,
+      1928, -14879,  -5066,  14950,  16498,   4773,   3842,   -425,
+     -1785,    -82,  10578,  -1435, -15554,  -2459,  16520,  16250,
+         0,      0,   9243,  14762,   5967,   1673,   3450,  12303,
+     -6027,   1394, -15022, -14571,   3402,  -4217, -10507,   -478,
+    -14813,  -5131,  -6634, -16293,    -82, -15276,  -1705,  -1731,
+       358,  -5738,  13681,  12503,  -8200,  -3023,  -3290,  -7384,
+      9272,   -837,  14328,  -1064,  16913,   7915,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_demixing_data[36] = {
+     16384,  16384,  16384,  16384,      0,      0,      0,  23170,
+         0, -23170,      0,      0, -16384,  16384, -16384,  16384,
+         0,      0,  23170,      0, -23170,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
+const opus_int16 mapping_matrix_soa_demixing_data[121] = {
+      2771,   2771,   2771,   2771,   2771,   2771,   2771,   2771,
+      2771,      0,      0,  10033,  10033, -20066,  10033,  14189,
+     14189, -28378,  10033, -20066,      0,      0,   3393,   3393,
+      3393,  -3393,      0,      0,      0,  -3393,  -3393,      0,
+         0, -17378,  17378,      0, -17378, -24576,  24576,      0,
+     17378,      0,      0,      0, -14189,  14189,      0, -14189,
+    -28378,  28378,      0,  14189,      0,      0,      0,   2399,
+      2399,  -4799,  -2399,      0,      0,      0,  -2399,   4799,
+         0,      0,   1959,   1959,   1959,   1959,  -3918,  -3918,
+     -3918,   1959,   1959,      0,      0,  -4156,   4156,      0,
+      4156,      0,      0,      0,  -4156,      0,      0,      0,
+      8192,   8192, -16384,   8192,  16384,  16384, -32768,   8192,
+    -16384,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,   8312,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+      8312
+};
+
+const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_demixing_data[324] = {
+      8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
+      8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
+         0,      0,      0,  -9779,   9779,   6263,   8857,      0,
+      6263,  13829,   9779, -13829,      0,  -6263,      0,  -8857,
+     -6263,  -9779,      0,      0,  -3413,   3413,   3413, -11359,
+     11359,  11359, -11359,  -3413,   3413,  -3413,  -3413, -11359,
+     11359,  11359, -11359,   3413,      0,      0,  13829,   9779,
+     -9779,   6263,      0,   8857,  -6263,      0,   9779,      0,
+    -13829,   6263,  -8857,      0,  -6263,  -9779,      0,      0,
+         0, -15617, -15617,   6406,      0,      0,  -6406,      0,
+     15617,      0,      0,  -6406,      0,      0,   6406,  15617,
+         0,      0,      0,  -5003,   5003, -10664,  15081,      0,
+    -10664,  -7075,   5003,   7075,      0,  10664,      0, -15081,
+     10664,  -5003,      0,      0,  -8176,  -8176,  -8176,   8208,
+      8208,   8208,   8208,  -8176,  -8176,  -8176,  -8176,   8208,
+      8208,   8208,   8208,  -8176,      0,      0,  -7075,   5003,
+     -5003, -10664,      0,  15081,  10664,      0,   5003,      0,
+      7075, -10664, -15081,      0,  10664,  -5003,      0,      0,
+     15617,      0,      0,      0,  -6406,   6406,      0, -15617,
+         0, -15617,  15617,      0,   6406,  -6406,      0,      0,
+         0,      0,      0, -11393,  11393,   2993,  -4233,      0,
+      2993, -16112,  11393,  16112,      0,  -2993,      0,   4233,
+     -2993, -11393,      0,      0,      0,  -9974,  -9974, -13617,
+         0,      0,  13617,      0,   9974,      0,      0,  13617,
+         0,      0, -13617,   9974,      0,      0,      0,   5579,
+     -5579,  10185,  14403,      0,  10185,  -7890,  -5579,   7890,
+         0, -10185,      0, -14403, -10185,   5579,      0,      0,
+     11826, -11826, -11826,   -901,    901,    901,   -901,  11826,
+    -11826,  11826,  11826,   -901,    901,    901,   -901, -11826,
+         0,      0,  -7890,  -5579,   5579,  10185,      0,  14403,
+    -10185,      0,  -5579,      0,   7890,  10185, -14403,      0,
+    -10185,   5579,      0,      0,  -9974,      0,      0,      0,
+    -13617,  13617,      0,   9974,      0,   9974,  -9974,      0,
+     13617, -13617,      0,      0,      0,      0,  16112, -11393,
+     11393,  -2993,      0,   4233,   2993,      0, -11393,      0,
+    -16112,  -2993,  -4233,      0,   2993,  11393,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_fourthoa_demixing = { 27, 27, 0 };
+const opus_int16 mapping_matrix_fourthoa_demixing_data[729] = {
+      4870,   4484,   4870,   4347,   4440,   4726,   4683,   4821,
+      4883,   4842,   4603,   4484,   4683,   4698,   4234,   4368,
+      4603,   4783,   4783,   4820,   4821,   4347,   4820,   4440,
+      4698,      0,      0,    101,     84,  -7818,   4640,  -7178,
+     -5492,   4629,   8384,   6547,  -4966,    617,  -6345,   1061,
+     -3241,   2939,   5549,   6390,  -4434,   4994,  -2610,   1993,
+     -2873,   1547,  -4356,   -164,      0,      0,   8797,   5074,
+     -1553,   5383,   1906,   5297,   2722,   1158,  -5226,   1311,
+     -7760,  -3327,  -1940,   1586,  -4093,  -2951,   -214,  -6873,
+      5450,  -4875,  -7193,  -4438,    558,   5593,   5607,      0,
+         0,    -26,   5761,  -3723,  -1460,   1195,  -3065,  -6357,
+     -1175,    608,   6965,   2310,   2759,  -8023,  -7138,   5162,
+     -3624,   5006,   -809,   3592,   6209,  -4159,  -4968,   8150,
+      2513,  -5702,      0,      0,    301,    109,   7161,  -2462,
+     -2443,   5044,  -7125,  -2256,   1967,  -9107,    259,  -4928,
+     -2592,   6514,   4111,  -7236,   8695,    635,   5009,  -4025,
+     -1937,   4794,   3420,  -3507,   -400,      0,      0,   -134,
+        85,   2771,   7842,  -3649,  -8225,   2866,   2586,  -9200,
+     -1945,  -1563,   6155,   -720,  -1061,  -3494,  -4513,   -487,
+      8389,   7317,   3348,  -3721,   3806,    371,  -6896,     70,
+         0,      0,  10919,   2072,  -4867,   3472,  -4429,   1721,
+     -4066,  -5193,   1032,  -5253,   9501,  -2017,  -3971,  -5261,
+      -306,  -2737,  -5137,   5713,   1237,     -8,   6387,    364,
+     -5423,   3364,   2888,      0,      0,    -48,   8946,   1048,
+     -2691,    602,  -4332,  -4302,   -514,  -1730,   2459,  -4328,
+     -2156,   3335,  -2748,  -6029,   4023,    155,    897,   5268,
+     -8380,   7625,   7395,    508,   3945,  -8951,      0,      0,
+        39,   4151,  -5965,  -3398,  -7006,  -3534,   2697,  -8989,
+     -5237,   2913,     46,  -5540,   8196,   5766,   2711,  -2520,
+     -3043,  -2146,   -948,   4965,   1806,   2472,   8988,  -1266,
+      4840,      0,      0,   -407,   -189,   2179,  -1627,   6516,
+       259,   7196,  -9449,  -4905,  -9766,    561,   4021,   3371,
+     -8650,   5032,   3329,   2534,    641,   2224,  -5747,   1047,
+     -4074,   5252,    -24,    674,      0,      0,    664,    237,
+     -2837,  -4072,  -1205,   8252,  -5875,  -1670,  -2743,  -3984,
+       381,   5059,   1765,   2666,  -8295,   7403,   1154,  -2086,
+      7622,   7105,   3677,  -6943,   1050,  -6632,   -694,      0,
+         0,    382,   -133,   5699,   7650,   5154,  -5713,  -1645,
+     -6902,   6181,   4450,   1151,    410,   -993,   3829,   2444,
+     -2405,  -6618,  -9514,   5366,  -1896,   5844,  -2886,  -1524,
+     -7321,  -1007,      0,      0,  12767,  -2530,   3183,  -1409,
+     -4015,  -2894,  -5155,  -1710,   3841,  -2107, -10274,   5119,
+      3979,  -4010,   5550,   4822,   -746,  -2507,  -3080,   4289,
+     -3675,   4333,  -1416,  -1230,  -1122,      0,      0,     17,
+      8048,   2398,  -2167,    -73,  -3606,   3125,    398,    731,
+     -5973,   5705,  -1032,   4679,   7305,   3134,   1301,  -3858,
+       -89,   2938,   4359,  -9155,  -4805,  -8407,   3673,  -8645,
+         0,      0,    187,   7355,   3145,  -6719,  -4432,  -5939,
+      2541,  -2810,   9723,    778,  -1105,   5687,  -4174,   2534,
+     -4461,   1017,   -244,   5481,  -1655,  -6765,  -3350,  -4894,
+      1592,  -2318,   8827,      0,      0,    196,   3588,   9631,
+      3063,  -4564,   6043,   2683,   2595,  -2488,  -2186,    173,
+     -6059,  -8270,  -2386,    409,   7441,  -8608,    376,  -4364,
+      2321,   -280,     97,   8331,  -3022,  -4721,      0,      0,
+       117,   -748, -10833,   1533,   4200,  -2875,   -997,   -109,
+     -3661,  -6119,   4454,   8808,  -9189,   8294,   1521,   7265,
+     -2348,  -5094,   -948,  -5400,  -3193,   8914,   5763,   1716,
+     -1070,      0,      0,   2497,    399,  -5201,  -2038,   7843,
+      -376,   7567,  -5073,   7616,  -5537,   2086,  -3453,  -5544,
+       -56, -11648,  -1314,   3546,  -3432,   -117,   8694,  -4245,
+      9621,   3098,  -2582,  -2351,      0,      0,   4386,  -3104,
+     -3132, -10512,    566,   5217,   5128,   4967,   1348,   7035,
+     -1470,     91,   -125,  -3548,   8244,  -3029, -10033,   2186,
+      9745,  -6440,  -2074,   3638,  -1477,  -7045,   -562,      0,
+         0,   2154,   8116,  -6102,   6570,  12998,   -712,  -4126,
+     -4996,     30,   1571,  -6393, -12794,    425,   5036,   1190,
+      5763,   5653,  12933,  -6671,   5197,  -2964,  -3316,  -6354,
+    -10554,  -2652,      0,      0,  12618,  -3737,     93,  -5901,
+      4262,  -3364,   4444,   3103,  -2767,   3403,   4925,  -2584,
+      -989,   4977,  -3714,  -1965,   3076,    326,  -2946,  -2568,
+      1026,  -2980,   3362,  -6132,  -5966,      0,      0,   6001,
+        48,  -1979,  -7275,   3476,  -2096,  10591,   3793,   2629,
+      -447, -14747,  -3689,  -5525,   8358,   6883,  -9703,  -4556,
+      7471,   2965,   4056,  13221,  -7327,  -3073,  -2353,  -6720,
+         0,      0,    621,  11034,    -44,  -2828,   5978,  -1850,
+     -1772,   3894,  -7471,  -1397,    945,  -2028,  -2928,  -2240,
+      3172,   2222,   4544,  -4243,  -5645,   3745,   2573,   3511,
+     -8206,  -7286,   5700,      0,      0,    321,  10818,  -4982,
+      7813,   -749,   9907,   1360,  -1443,    568,  -1103,   2305,
+      6045,   2270,  -1063,  -1920,  -3073,   5893,  -3476, -11346,
+     -1657,   -588,   2957,  -2287,  -8527,  -8041,      0,      0,
+       119,   -268,   2372,  -3040,   4979,  -3789,  -5630,  10619,
+      5900,  -5109,  -4585,  -3862,  10467,  -3527,   -385, -10034,
+     -9991,   4860,    984,   2362,   2311,  -6804,   6324,    433,
+      5291,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767
+};
+
+const MappingMatrix mapping_matrix_fifthoa_demixing = { 38, 38, 0 };
+const opus_int16 mapping_matrix_fifthoa_demixing_data[1444] = {
+      3188,   3247,   3268,   3368,   3368,   3138,   3268,   3099,
+      3211,   3368,   3099,   3247,   3211,   3368,   3368,   3368,
+      3149,   3268,   3247,   3211,   3099,   3188,   3138,   3149,
+      3099,   3188,   3368,   3149,   3188,   3247,   3268,   3138,
+      3211,   3368,   3138,   3149,      0,      0,    118,    -47,
+     -5011,    282,    333,  -1497,  -4584,   2908,   3388,  -3647,
+     -2493,   1139,  -2882,  -1719,   3604,  -2543,  -4328,   5443,
+      1286,  -5498,  -4583,   2510,  -1743,  -2556,   4168,   1446,
+      -290,   1812,  -4074,  -2377,   4152,   2847,   4991,   3980,
+       393,   5072,      0,      0,   5489,  -2235,   1507,  -5326,
+      4609,  -1096,   2926,  -3427,  -3301,  -3078,   4226,   1730,
+      4627,   2561,   2966,   -592,    143,   -677,   4617,   -755,
+      -956,   -433,  -5138,   3037,    157,  -1394,  -4498,  -4984,
+     -3661,  -4112,  -3756,   4628,   -570,   3356,   1605,   1803,
+         0,      0,   -162,   5162,   2132,   2392,   3556,  -5141,
+     -1536,   2975,  -3001,  -3350,  -2231,  -5230,   1294,  -4965,
+      3494,   5230,  -3292,  -1359,  -2945,   -773,   2670,   4867,
+      -660,   3720,  -3415,  -5112,  -3700,  -1211,    407,   3013,
+       763,    591,   2481,  -2657,   5210,    784,      0,      0,
+      -156,    338,  -4246,    510,    462,   3296,   2846,   3333,
+     -4292,   4574,   1940,  -2986,  -1275,   3701,   5022,  -5250,
+      5780,  -2676,  -1180,   1516,  -4852,   4877,    342,  -3923,
+     -5703,  -2920,    379,   -657,   -361,  -3346,   1044,    795,
+      5257,  -4004,    698,   1115,      0,      0,     47,   -140,
+     -3292,  -1097,    652,    855,  -5260,  -3691,  -4470,   4521,
+     -3863,   1093,  -5552,  -2016,   3831,    334,   -456,  -1532,
+      2068,   1788,   2054,   -295,   3668,  -2820,    328,   -994,
+       295,  -3301,   5770,   4282,  -6353,   5632,  -1371,   5005,
+       238,   4041,      0,      0,   6764,  -1659,  -2730,   5726,
+      3715,  -3216,   -933,    531,    -52,   -345,   3022,  -2818,
+      4005,  -1617,  -1189,  -3748,  -3403,  -3592,   4040,  -3553,
+     -2806,  -3444,   6023,   -711,  -3298,  -2503,   2548,   5564,
+       940,   1848,   1207,   4010,  -3488,   -358,  -2511,  -1966,
+         0,      0,    -64,  -5039,   1403,  -4455,   6240,   2189,
+     -1716,  -4348,   4183,   3951,  -4042,  -3606,   2399,  -4563,
+      4050,   -612,   -395,    348,  -5791,    391,  -1440,   -735,
+      1398,   4359,   -518,   2969,   6556,   1951,   -518,  -4993,
+      -925,    998,   -569,  -2934,   3460,    420,      0,      0,
+        16,   5482,  -4122,    770,   2082,   5020,  -3961,    485,
+      -584,   -793,      3,   5222,  -1416,   3673,     78,   3549,
+      -937,  -5723,   1673,  -6162,  -2540,   3082,   -355,   1838,
+      -615,   4601,   2832,   -359,  -3346,    668,  -3393,  -1583,
+     -3774,  -2206,   5754,  -4961,      0,      0,   -328,    299,
+      2470,    317,    525,  -4494,   2805,   2617,   2383,  -2363,
+     -1037,   4085,    895,  -4622,   3218,  -6607,  -3381,  -5933,
+      1397,   6394,   -446,   5694,     14,  -4510,   4329,   3690,
+      -334,      0,   2932,  -2478,  -2944,   -577,   -599,   -230,
+      1553,  -4736,      0,      0,   -324,    142,  -3252,   -867,
+      1111,  -1882,   3378,  -6055,   6502,  -6840,   4280,  -2694,
+     -2876,   4190,   6454,    655,   1061,    626,  -2669,   -798,
+      3192,   -985,   -898,  -5482,   -548,   2315,   -558,   1302,
+       900,   5747,  -1325,   1599,  -1384,  -5749,    624,   1110,
+         0,      0,    321,    312,   2188,   1322,    237,    708,
+      -304,   2463,   1500,  -1094,  -5112,  -1010,  -6799,    646,
+       992,   1969,   3423,  -3996,   2628,   4451,   3432,  -2833,
+     -6101,   -330,  -3768,     -3,   -707,   5961,  -4037,  -3736,
+      4080,   7254,  -4113,   2151,     54,  -2150,      0,      0,
+      7735,   4064,  -3884,  -5240,    577,   2229,  -3947,   2914,
+      3555,   4011,    774,  -3519,   1985,  -3701,  -3824,    330,
+      -905,   2085,   1155,   2176,   3006,    340,  -5533,  -3264,
+      -902,   3114,    344,  -5060,   1524,   1805,   1926,   2350,
+      1905,  -3203,  -2762,  -4162,      0,      0,    193,   -151,
+     -1434,   6289,   7354,   4234,    169,   2868,  -1977,  -1375,
+     -4987,   2345,   2742,    599,    939,  -4837,   2688,    991,
+     -6907,    716,  -1542,  -4346,  -1833,   1493,   3134,   2903,
+     -7019,  -2835,     93,   4395,    621,    870,  -2357,   -975,
+     -2933,   -127,      0,      0,   -616,  -5968,  -3479,  -1651,
+      4932,  -2445,  -5512,  -1451,    691,    739,    479,   4227,
+     -2886,   3853,      8,   -501,    188,   1990,   3842,   2270,
+      1662,   -174,   1290,   2456,     67,  -3267,  -5535,    483,
+      5721,  -1642,   6501,  -3432,   1184,  -3246,   4101,  -4880,
+         0,      0,   -465,   5264,  -4812,    682,   1683,  -4539,
+      2916,  -1985,   2899,   3324,   1060,  -4398,   -745,  -2137,
+     -3827,   1044,   6225,   3609,   -532,   1980,  -6001,    564,
+      -209,  -1299,   5336,  -3605,  -1484,     37,     19,  -1295,
+      -665,   -385,  -6773,   3651,   6153,  -1291,      0,      0,
+       193,   -415,   5166,   -110,    626,   6743,  -2860,   1425,
+      1101,  -1341,     80,  -4533,    249,   4231,   -119,  -6009,
+     -2970,   5170,   -822,  -2610,   4527,   5948,    182,  -2589,
+       837,  -5471,    371,    -43,    373,   -665,  -1233,   -626,
+     -7353,   2606,   1339,  -1398,      0,      0,   -533,    147,
+      2075,   -672,   1043,   3503,   4402,  -4971,  -3287,   3731,
+     -2606,   3817,   1972,  -5603,   5114,   1185,  -1318,   1906,
+      3018,  -1999,    343,  -1943,    207,  -6744,    913,  -4060,
+       645,   -349,  -5667,   4766,   5575,  -1733,   1116,    160,
+      1534,  -5690,      0,      0,   -137,    -36,   1556,   1325,
+      1553,  -2230,   1188,   5296,  -5104,   4673,   6295,    498,
+     -4723,    933,   2994,   4067,  -4700,   1758,  -4116,  -1252,
+      2444,  -4092,   1653,  -2802,   5069,   1133,    790,  -2355,
+      -934,  -6304,   1642,   2045,  -4259,  -3873,   -213,    215,
+         0,      0,   -364,    423,   4888,  -1316,    118,   -950,
+      4027,    114,   2961,  -3136,  -3012,   -883,  -6192,   1340,
+     -3210,  -1193,   1376,   3128,   1596,  -2994,  -3194,    533,
+      8502,   2487,  -1485,   1032,    301,  -8007,   -577,    887,
+       297,   7778,   3121,  -1901,    -94,  -6401,      0,      0,
+      9260,  -1845,    668,   2787,  -2255,   2699,  -2512,  -3737,
+     -3675,  -3601,  -1803,    210,  -1701,  -1442,  -2700,   3457,
+      2868,   2079,  -2113,   3178,   1277,   3578,   5240,  -2482,
+      3324,   1020,  -4027,   3835,  -3758,  -3633,  -3170,  -1310,
+      2509,  -3110,    713,    174,      0,      0,   -399,   4969,
+     -2321,  -7744,   6494,  -3776,   1478,    758,  -1794,  -2233,
+     -4059,   4932,   2770,   4761,  -3475,   1243,    829,   -651,
+     -5358,   -436,   2381,   1360,   2561,  -3118,    858,  -4366,
+      3933,   3646,    -43,  -1310,    -16,    924,   1197,   1415,
+     -5036,   -376,      0,      0,    100,   1410,   1290,   3199,
+      7091,  -3638,  -2641,   1118,     45,   -441,    794,   -974,
+     -5033,    889,    438,  -3102,    895,   3555,   4672,   4795,
+      1129,  -2408,  -2153,   1742,    159,  -2040,   7578,  -2006,
+     -5737,   1986,  -5568,  -6413,   2428,  -1387,  -2441,    667,
+         0,      0,    -37,  -6031,  -4434,   -904,   3290,   1806,
+      4736,   2516,  -5905,  -5927,   1754,  -4300,  -2468,  -2203,
+     -4836,   -672,   1444,  -1591,  -1631,  -1789,   4311,   -153,
+      -688,  -1222,   1058,   3139,   4659,   -353,   1543,   1838,
+      2180,  -1448,   2432,   6277,   5304,  -1692,      0,      0,
+      -280,   4506,    807,   -477,    823,   3550,   1427,  -1856,
+     -3003,  -3501,  -1203,   2679,    933,    778,  -4954,  -1977,
+     -7458,   4687,    435,   7045,  -4053,  -3130,    257,  -3917,
+     -6165,   1889,    927,    235,   1889,  -1097,   1985,    630,
+     -2172,  -2130,   7080,   4810,      0,      0,   -300,    496,
+      2808,    279,    667,  -7179,  -2661,   -526,  -2832,   1751,
+      2849,   4829,   -906,  -4151,  -1124,  -3062,   8166,   5361,
+     -1656,  -6017,   3265,   2551,   -864,   -432,  -6966,   6295,
+      -168,    901,    442,   -582,    269,    236,  -3574,    799,
+       472,    565,      0,      0,    805,  -2466,   6208,  -4592,
+      -170,  -6701,  -5610,   3678,  -4242,   4561,   -724,  -5534,
+      2415,   7354,   2761,   2699,   -349,   3822,  -2372,   1756,
+     -5523,  -3445,   -588,  -5749,  -3986,   9804,  -3871,   5375,
+     -2308,   5504,  -2766,  -1651,   1472,   6832,   2705,  -5104,
+         0,      0,   -700,  -1179,   4402,    400,   1383,    939,
+     -1342,   6013,   2577,  -3472,    472,   2883,   1450,  -3917,
+      2849,   5084,   4990,   5392,    342,  -4925,  -3329,  -5372,
+     -2674,  -6035,  -5072,   -836,    179,   2506,   7987,  -3647,
+     -8202,  -1437,   1891,   2400,   1607,  -3611,      0,      0,
+     -4706,  -4003,   9928,   -379,   5557,   3738,  -8789,    685,
+      1937,  -5157,  13388,   7995,  -4119,  -9909,  -5079,   4804,
+      5586,    774,  -5430,    299,  -9943,   3264,  -3690,  -3901,
+     -1133,  -6199,   3182,   1544,   5467,   3686,  -2639,   4068,
+      1163,   -185,  -1299,   -506,      0,      0,    843,   1005,
+     -1059,    467,  -1279,  -2259,   6057,  -1694,  -5885,   5342,
+     -5160,  -3748,  -1382,   4420,   -697,  -2000,  -3808,   3100,
+      2685,  -4073,    531,    318,  -7822,   2414,   2901,   3399,
+     -1340,   8449,   3685,    463,  -3341,   2423,   2304,  -2723,
+        84,  -2622,      0,      0,  12088,   -265,   2562,   -435,
+     -4348,  -2426,   3538,   1552,   1279,    883,  -4166,   2634,
+     -6130,   2994,   3729,  -1570,   -601,  -1753,  -5124,  -2788,
+     -2096,  -1920,  -2649,   2793,  -1079,  -1952,   2983,  -1530,
+      2499,   1769,   1492,  -6757,  -2108,   2841,   1466,   2597,
+         0,      0,  -3830,  -4093,   2448,  12720,   7737,   -665,
+      -832,  -9257,   2971,  -2400,    791,   1873,   1072,   -587,
+     -7440,   8055,   1531,  -4736,    616,  -1782,  -2982,   9663,
+     -5057,  -5926,   1610,  -4489,   7033,  -8658,   6010,  -5673,
+      5648,    812,   -271,  -1802,  -4500,   4392,      0,      0,
+      -888,   -327,   3373,  -1084,   7959,   2430,   1898,  -2360,
+     -1820,  -1377,  -1090,  -4436,  -3422,  -1106,  -3230,   3876,
+       -41,  -5128,   6375,  -1848,  -3824,   5844,    617,  -1957,
+      4232,   1345,  -1439,    -83,   3046,   -214,   5458,  -5566,
+     -4387,  -3738,  -5740,   8657,      0,      0,   6978,   6239,
+     -3686,   -981,  -2854,     78,   5859,   -357,   4618,   7391,
+      -138,    971,  -5799,   2135,   4478,  -7004,  -5949,   1668,
+     -6933,  -1163,   7010,  -5624,   2990,   6192,  -8075,   3567,
+     -8308,   2236,  -5098,  -2120,  -4355,  -4238,   4955,  10230,
+       692,  -5606,      0,      0,  -1348,  -7069,    -12,  -4927,
+      1211,    651,   1360,   7744,   3404,   5069,  -2438,   -105,
+      2332,   1494,  -4686,   1336,  -3628,   -881,   2474,   1736,
+       -26,   -257,   2135,  -4452,    446,   -641,  -4704,   2605,
+     -6436,   6662,  -4939,    990,  -1100,  -3782,   5028,   4753,
+         0,      0,  -2875,   6410,   3518,   3950,   1271,    869,
+     -2842,  -5837,   1532,  -2899,   1140,   -597,   1712,  -1988,
+     -4819,  -4783,   4773,  -8796,   2240,  -4596,   3565,  -4853,
+      -556,  -3974,   7366,  -4370,   3113,  -3548,   3552,  -5450,
+      3869,   2514,   6736,  -4570,   6074,   3151,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.h b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mapping_matrix.h
new file mode 100644 (file)
index 0000000..eedf232
--- /dev/null
@@ -0,0 +1,157 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file mapping_matrix.h
+ * @brief Opus reference implementation mapping matrix API
+ */
+
+#ifndef MAPPING_MATRIX_H
+#define MAPPING_MATRIX_H
+
+#include "opus_types.h"
+#include "opus_projection.h"
+
+typedef struct MappingMatrix
+{
+    int rows; /* number of channels outputted from matrix. */
+    int cols; /* number of channels inputted to matrix. */
+    int gain; /* in dB. S7.8-format. */
+    /* Matrix cell data goes here using col-wise ordering. */
+} MappingMatrix;
+
+opus_int32 mapping_matrix_get_size(int rows, int cols);
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
+
+void mapping_matrix_init(
+    MappingMatrix * const matrix,
+    int rows,
+    int cols,
+    int gain,
+    const opus_int16 *data,
+    opus_int32 data_size
+);
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+    const MappingMatrix *matrix,
+    const float *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_float(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    float *output,
+    int output_rows,
+    int frame_size
+);
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+    const MappingMatrix *matrix,
+    const opus_int16 *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_short(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    opus_int16 *output,
+    int output_rows,
+    int frame_size
+);
+
+
+void mapping_matrix_multiply_channel_in_int24(
+    const MappingMatrix *matrix,
+    const opus_int32 *input,
+    int input_rows,
+    opus_res *output,
+    int output_row,
+    int output_rows,
+    int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_int24(
+    const MappingMatrix *matrix,
+    const opus_res *input,
+    int input_row,
+    int input_rows,
+    opus_int32 *output,
+    int output_rows,
+    int frame_size
+);
+/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
+ *   foa: first-order ambisonics
+ *   soa: second-order ambisonics
+ *   toa: third-order ambisonics
+ */
+extern const MappingMatrix mapping_matrix_foa_mixing;
+extern const opus_int16 mapping_matrix_foa_mixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_mixing;
+extern const opus_int16 mapping_matrix_soa_mixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_mixing;
+extern const opus_int16 mapping_matrix_toa_mixing_data[324];
+
+extern const MappingMatrix mapping_matrix_fourthoa_mixing;
+extern const opus_int16 mapping_matrix_fourthoa_mixing_data[729];
+
+extern const MappingMatrix mapping_matrix_fifthoa_mixing;
+extern const opus_int16 mapping_matrix_fifthoa_mixing_data[1444];
+
+extern const MappingMatrix mapping_matrix_foa_demixing;
+extern const opus_int16 mapping_matrix_foa_demixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_demixing;
+extern const opus_int16 mapping_matrix_soa_demixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_demixing;
+extern const opus_int16 mapping_matrix_toa_demixing_data[324];
+
+extern const MappingMatrix mapping_matrix_fourthoa_demixing;
+extern const opus_int16 mapping_matrix_fourthoa_demixing_data[729];
+
+extern const MappingMatrix mapping_matrix_fifthoa_demixing;
+extern const opus_int16 mapping_matrix_fifthoa_demixing_data[1444];
+
+#endif /* MAPPING_MATRIX_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mlp.h b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/mlp.h
new file mode 100644 (file)
index 0000000..e6b1a8f
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright (c) 2017 Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef MLP_H_
+#define MLP_H_
+
+#include "opus_types.h"
+
+#define WEIGHTS_SCALE (1.f/128)
+
+#define MAX_NEURONS 32
+
+typedef struct {
+  const opus_int8 *bias;
+  const opus_int8 *input_weights;
+  int nb_inputs;
+  int nb_neurons;
+  int sigmoid;
+} AnalysisDenseLayer;
+
+typedef struct {
+  const opus_int8 *bias;
+  const opus_int8 *input_weights;
+  const opus_int8 *recurrent_weights;
+  int nb_inputs;
+  int nb_neurons;
+} AnalysisGRULayer;
+
+extern const AnalysisDenseLayer layer0;
+extern const AnalysisGRULayer layer1;
+extern const AnalysisDenseLayer layer2;
+
+void analysis_compute_dense(const AnalysisDenseLayer *layer, float *output, const float *input);
+
+void analysis_compute_gru(const AnalysisGRULayer *gru, float *state, const float *input);
+
+#endif /* MLP_H_ */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus.c
new file mode 100644 (file)
index 0000000..01be689
--- /dev/null
@@ -0,0 +1,398 @@
+/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
+   Copyright (c) 2024 Arm Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus.h"
+#include "mathops.h"
+#include "opus_private.h"
+
+#ifndef DISABLE_FLOAT_API
+
+void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch)
+{
+   int c;
+   int i;
+   float *x;
+   int all_within_neg1pos1;
+
+   if (C<1 || N<1 || !_x || !declip_mem) return;
+
+   /* Clamp everything within the range [-2, +2] which is the domain of the soft
+      clipping non-linearity. Outside the defined range the derivative will be zero,
+      therefore there is no discontinuity introduced here. The implementation
+      might provide a hint if all input samples are within the [-1, +1] range.
+
+   `opus_limit2_checkwithin1()`:
+      - Clamps all samples within the valid range [-2, +2].
+      - Generic C implementation:
+         * Does not attempt early detection whether samples are within hinted range.
+         * Always returns 0.
+      - Architecture specific implementation:
+         * Uses SIMD instructions to efficiently detect if all samples are
+           within the hinted range [-1, +1].
+         * Returns 1 if no samples exceed the hinted range, 0 otherwise.
+
+   `all_within_neg1pos1`:
+      - Optimization hint to skip per-sample out-of-bound checks.
+        If true, the check can be skipped. */
+   all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
+
+   for (c=0;c<C;c++)
+   {
+      float a;
+      float x0;
+      int curr;
+
+      x = _x+c;
+      a = declip_mem[c];
+      /* Continue applying the non-linearity from the previous frame to avoid
+         any discontinuity. */
+      for (i=0;i<N;i++)
+      {
+         if (x[i*C]*a>=0)
+            break;
+         x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
+      }
+
+      curr=0;
+      x0 = x[0];
+      while(1)
+      {
+         int start, end;
+         float maxval;
+         int special=0;
+         int peak_pos;
+         /* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
+         if (all_within_neg1pos1)
+         {
+            i = N;
+         } else {
+            for (i=curr;i<N;i++)
+            {
+               if (x[i*C]>1 || x[i*C]<-1)
+                  break;
+            }
+         }
+         if (i==N)
+         {
+            a=0;
+            break;
+         }
+         peak_pos = i;
+         start=end=i;
+         maxval=ABS16(x[i*C]);
+         /* Look for first zero crossing before clipping */
+         while (start>0 && x[i*C]*x[(start-1)*C]>=0)
+            start--;
+         /* Look for first zero crossing after clipping */
+         while (end<N && x[i*C]*x[end*C]>=0)
+         {
+            /* Look for other peaks until the next zero-crossing. */
+            if (ABS16(x[end*C])>maxval)
+            {
+               maxval = ABS16(x[end*C]);
+               peak_pos = end;
+            }
+            end++;
+         }
+         /* Detect the special case where we clip before the first zero crossing */
+         special = (start==0 && x[i*C]*x[0]>=0);
+
+         /* Compute a such that maxval + a*maxval^2 = 1 */
+         a=(maxval-1)/(maxval*maxval);
+         /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
+            does not cause output values larger than +/-1, but small enough not
+            to matter even for 24-bit output.  */
+         a += a*2.4e-7f;
+         if (x[i*C]>0)
+            a = -a;
+         /* Apply soft clipping */
+         for (i=start;i<end;i++)
+            x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
+
+         if (special && peak_pos>=2)
+         {
+            /* Add a linear ramp from the first sample to the signal peak.
+               This avoids a discontinuity at the beginning of the frame. */
+            float delta;
+            float offset = x0-x[0];
+            delta = offset / peak_pos;
+            for (i=curr;i<peak_pos;i++)
+            {
+               offset -= delta;
+               x[i*C] += offset;
+               x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
+            }
+         }
+         curr = end;
+         if (curr==N)
+            break;
+      }
+      declip_mem[c] = a;
+   }
+}
+
+OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
+{
+   opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
+}
+
+#endif
+
+int encode_size(int size, unsigned char *data)
+{
+   if (size < 252)
+   {
+      data[0] = size;
+      return 1;
+   } else {
+      data[0] = 252+(size&0x3);
+      data[1] = (size-(int)data[0])>>2;
+      return 2;
+   }
+}
+
+static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
+{
+   if (len<1)
+   {
+      *size = -1;
+      return -1;
+   } else if (data[0]<252)
+   {
+      *size = data[0];
+      return 1;
+   } else if (len<2)
+   {
+      *size = -1;
+      return -1;
+   } else {
+      *size = 4*data[1] + data[0];
+      return 2;
+   }
+}
+
+int opus_packet_get_samples_per_frame(const unsigned char *data,
+      opus_int32 Fs)
+{
+   int audiosize;
+   if (data[0]&0x80)
+   {
+      audiosize = ((data[0]>>3)&0x3);
+      audiosize = (Fs<<audiosize)/400;
+   } else if ((data[0]&0x60) == 0x60)
+   {
+      audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
+   } else {
+      audiosize = ((data[0]>>3)&0x3);
+      if (audiosize == 3)
+         audiosize = Fs*60/1000;
+      else
+         audiosize = (Fs<<audiosize)/100;
+   }
+   return audiosize;
+}
+
+int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
+      int self_delimited, unsigned char *out_toc,
+      const unsigned char *frames[48], opus_int16 size[48],
+      int *payload_offset, opus_int32 *packet_offset,
+      const unsigned char **padding, opus_int32 *padding_len)
+{
+   int i, bytes;
+   int count;
+   int cbr;
+   unsigned char ch, toc;
+   int framesize;
+   opus_int32 last_size;
+   opus_int32 pad = 0;
+   const unsigned char *data0 = data;
+
+   /* Make sure we return NULL/0 on error. */
+   if (padding != NULL)
+   {
+      *padding = NULL;
+      *padding_len = 0;
+   }
+
+   if (size==NULL || len<0)
+      return OPUS_BAD_ARG;
+   if (len==0)
+      return OPUS_INVALID_PACKET;
+
+   framesize = opus_packet_get_samples_per_frame(data, 48000);
+
+   cbr = 0;
+   toc = *data++;
+   len--;
+   last_size = len;
+   switch (toc&0x3)
+   {
+   /* One frame */
+   case 0:
+      count=1;
+      break;
+   /* Two CBR frames */
+   case 1:
+      count=2;
+      cbr = 1;
+      if (!self_delimited)
+      {
+         if (len&0x1)
+            return OPUS_INVALID_PACKET;
+         last_size = len/2;
+         /* If last_size doesn't fit in size[0], we'll catch it later */
+         size[0] = (opus_int16)last_size;
+      }
+      break;
+   /* Two VBR frames */
+   case 2:
+      count = 2;
+      bytes = parse_size(data, len, size);
+      len -= bytes;
+      if (size[0]<0 || size[0] > len)
+         return OPUS_INVALID_PACKET;
+      data += bytes;
+      last_size = len-size[0];
+      break;
+   /* Multiple CBR/VBR frames (from 0 to 120 ms) */
+   default: /*case 3:*/
+      if (len<1)
+         return OPUS_INVALID_PACKET;
+      /* Number of frames encoded in bits 0 to 5 */
+      ch = *data++;
+      count = ch&0x3F;
+      if (count <= 0 || framesize*(opus_int32)count > 5760)
+         return OPUS_INVALID_PACKET;
+      len--;
+      /* Padding flag is bit 6 */
+      if (ch&0x40)
+      {
+         int p;
+         do {
+            int tmp;
+            if (len<=0)
+               return OPUS_INVALID_PACKET;
+            p = *data++;
+            len--;
+            tmp = p==255 ? 254: p;
+            len -= tmp;
+            pad += tmp;
+         } while (p==255);
+      }
+      if (len<0)
+         return OPUS_INVALID_PACKET;
+      /* VBR flag is bit 7 */
+      cbr = !(ch&0x80);
+      if (!cbr)
+      {
+         /* VBR case */
+         last_size = len;
+         for (i=0;i<count-1;i++)
+         {
+            bytes = parse_size(data, len, size+i);
+            len -= bytes;
+            if (size[i]<0 || size[i] > len)
+               return OPUS_INVALID_PACKET;
+            data += bytes;
+            last_size -= bytes+size[i];
+         }
+         if (last_size<0)
+            return OPUS_INVALID_PACKET;
+      } else if (!self_delimited)
+      {
+         /* CBR case */
+         last_size = len/count;
+         if (last_size*count!=len)
+            return OPUS_INVALID_PACKET;
+         for (i=0;i<count-1;i++)
+            size[i] = (opus_int16)last_size;
+      }
+      break;
+   }
+   /* Self-delimited framing has an extra size for the last frame. */
+   if (self_delimited)
+   {
+      bytes = parse_size(data, len, size+count-1);
+      len -= bytes;
+      if (size[count-1]<0 || size[count-1] > len)
+         return OPUS_INVALID_PACKET;
+      data += bytes;
+      /* For CBR packets, apply the size to all the frames. */
+      if (cbr)
+      {
+         if (size[count-1]*count > len)
+            return OPUS_INVALID_PACKET;
+         for (i=0;i<count-1;i++)
+            size[i] = size[count-1];
+      } else if (bytes+size[count-1] > last_size)
+         return OPUS_INVALID_PACKET;
+   } else
+   {
+      /* Because it's not encoded explicitly, it's possible the size of the
+         last packet (or all the packets, for the CBR case) is larger than
+         1275. Reject them here.*/
+      if (last_size > 1275)
+         return OPUS_INVALID_PACKET;
+      size[count-1] = (opus_int16)last_size;
+   }
+
+   if (payload_offset)
+      *payload_offset = (int)(data-data0);
+
+   for (i=0;i<count;i++)
+   {
+      if (frames)
+         frames[i] = data;
+      data += size[i];
+   }
+
+   if (padding != NULL)
+   {
+      *padding = data;
+      *padding_len = pad;
+   }
+   if (packet_offset)
+      *packet_offset = pad+(opus_int32)(data-data0);
+
+   if (out_toc)
+      *out_toc = toc;
+
+   return count;
+}
+
+int opus_packet_parse(const unsigned char *data, opus_int32 len,
+      unsigned char *out_toc, const unsigned char *frames[48],
+      opus_int16 size[48], int *payload_offset)
+{
+   return opus_packet_parse_impl(data, len, 0, out_toc,
+                                 frames, size, payload_offset, NULL, NULL, NULL);
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_decoder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_decoder.c
new file mode 100644 (file)
index 0000000..1678e1e
--- /dev/null
@@ -0,0 +1,1691 @@
+/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
+   Copyright (c) 2024 Arm Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef OPUS_BUILD
+# error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details."
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) && !defined(OPUS_WILL_BE_SLOW)
+# pragma message "You appear to be compiling without optimization, if so opus will be very slow."
+#endif
+
+#include <stdarg.h>
+#include "celt.h"
+#include "opus.h"
+#include "entdec.h"
+#include "modes.h"
+#include "API.h"
+#include "stack_alloc.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "os_support.h"
+#include "structs.h"
+#include "define.h"
+#include "mathops.h"
+#include "cpu_support.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "dred_rdovae_dec_data.h"
+#include "dred_rdovae_dec.h"
+#endif
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+struct OpusDecoder {
+   int          celt_dec_offset;
+   int          silk_dec_offset;
+   int          channels;
+   opus_int32   Fs;          /** Sampling rate (at the API level) */
+   silk_DecControlStruct DecControl;
+   int          decode_gain;
+   int          complexity;
+   int          ignore_extensions;
+   int          arch;
+#ifdef ENABLE_DEEP_PLC
+    LPCNetPLCState lpcnet;
+#endif
+
+   /* Everything beyond this point gets cleared on a reset */
+#define OPUS_DECODER_RESET_START stream_channels
+   int          stream_channels;
+
+   int          bandwidth;
+   int          mode;
+   int          prev_mode;
+   int          frame_size;
+   int          prev_redundancy;
+   int          last_packet_duration;
+#ifndef FIXED_POINT
+   opus_val16   softclip_mem[2];
+#endif
+
+   opus_uint32  rangeFinal;
+};
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_opus_decoder(OpusDecoder *st)
+{
+   celt_assert(st->channels == 1 || st->channels == 2);
+#ifdef ENABLE_QEXT
+   celt_assert(st->Fs == 96000 || st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
+#else
+   celt_assert(st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
+#endif
+   celt_assert(st->DecControl.API_sampleRate == st->Fs);
+   celt_assert(st->DecControl.internalSampleRate == 0 || st->DecControl.internalSampleRate == 16000 || st->DecControl.internalSampleRate == 12000 || st->DecControl.internalSampleRate == 8000);
+   celt_assert(st->DecControl.nChannelsAPI == st->channels);
+   celt_assert(st->DecControl.nChannelsInternal == 0 || st->DecControl.nChannelsInternal == 1 || st->DecControl.nChannelsInternal == 2);
+   celt_assert(st->DecControl.payloadSize_ms == 0 || st->DecControl.payloadSize_ms == 10 || st->DecControl.payloadSize_ms == 20 || st->DecControl.payloadSize_ms == 40 || st->DecControl.payloadSize_ms == 60);
+#ifdef OPUS_ARCHMASK
+   celt_assert(st->arch >= 0);
+   celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+   celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+}
+#define VALIDATE_OPUS_DECODER(st) validate_opus_decoder(st)
+#else
+#define VALIDATE_OPUS_DECODER(st)
+#endif
+
+int opus_decoder_get_size(int channels)
+{
+   int silkDecSizeBytes, celtDecSizeBytes;
+   int ret;
+   if (channels<1 || channels > 2)
+      return 0;
+   ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
+   if(ret)
+      return 0;
+   silkDecSizeBytes = align(silkDecSizeBytes);
+   celtDecSizeBytes = celt_decoder_get_size(channels);
+   return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
+}
+
+int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
+{
+   void *silk_dec;
+   CELTDecoder *celt_dec;
+   int ret, silkDecSizeBytes;
+
+   if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000
+#ifdef ENABLE_QEXT
+         &&Fs!=96000
+#endif
+         )
+    || (channels!=1&&channels!=2))
+      return OPUS_BAD_ARG;
+
+   OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
+   /* Initialize SILK decoder */
+   ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
+   if (ret)
+      return OPUS_INTERNAL_ERROR;
+
+   silkDecSizeBytes = align(silkDecSizeBytes);
+   st->silk_dec_offset = align(sizeof(OpusDecoder));
+   st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
+   silk_dec = (char*)st+st->silk_dec_offset;
+   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+   st->stream_channels = st->channels = channels;
+   st->complexity = 0;
+
+   st->Fs = Fs;
+   st->DecControl.API_sampleRate = st->Fs;
+   st->DecControl.nChannelsAPI      = st->channels;
+
+   /* Reset decoder */
+   ret = silk_InitDecoder( silk_dec );
+   if(ret)return OPUS_INTERNAL_ERROR;
+
+   /* Initialize CELT decoder */
+   ret = celt_decoder_init(celt_dec, Fs, channels);
+   if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;
+
+   celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
+
+   st->prev_mode = 0;
+   st->frame_size = Fs/400;
+#ifdef ENABLE_DEEP_PLC
+    lpcnet_plc_init( &st->lpcnet);
+#endif
+   st->arch = opus_select_arch();
+   return OPUS_OK;
+}
+
+OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
+{
+   int ret;
+   OpusDecoder *st;
+   if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000
+#ifdef ENABLE_QEXT
+         &&Fs!=96000
+#endif
+         )
+    || (channels!=1&&channels!=2))
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+   st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels));
+   if (st == NULL)
+   {
+      if (error)
+         *error = OPUS_ALLOC_FAIL;
+      return NULL;
+   }
+   ret = opus_decoder_init(st, Fs, channels);
+   if (error)
+      *error = ret;
+   if (ret != OPUS_OK)
+   {
+      opus_free(st);
+      st = NULL;
+   }
+   return st;
+}
+
+#ifdef ENABLE_RES24
+static void smooth_fade(const opus_res *in1, const opus_res *in2,
+      opus_res *out, int overlap, int channels,
+      const celt_coef *window, opus_int32 Fs)
+{
+   int i, c;
+   int inc = 48000/Fs;
+   for (c=0;c<channels;c++)
+   {
+      for (i=0;i<overlap;i++)
+      {
+         celt_coef w = MULT_COEF(window[i*inc], window[i*inc]);
+         out[i*channels+c] = ADD32(MULT_COEF_32(w,in2[i*channels+c]),
+                                   MULT_COEF_32(COEF_ONE-w, in1[i*channels+c]));
+      }
+   }
+}
+#else
+static void smooth_fade(const opus_res *in1, const opus_res *in2,
+      opus_res *out, int overlap, int channels,
+      const celt_coef *window, opus_int32 Fs)
+{
+   int i, c;
+   int inc = 48000/Fs;
+   for (c=0;c<channels;c++)
+   {
+      for (i=0;i<overlap;i++)
+      {
+         opus_val16 w = COEF2VAL16(window[i*inc]);
+         w = MULT16_16_Q15(w, w);
+         out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
+                                   Q15ONE-w, in1[i*channels+c]), 15);
+      }
+   }
+}
+#endif
+
+static int opus_packet_get_mode(const unsigned char *data)
+{
+   int mode;
+   if (data[0]&0x80)
+   {
+      mode = MODE_CELT_ONLY;
+   } else if ((data[0]&0x60) == 0x60)
+   {
+      mode = MODE_HYBRID;
+   } else {
+      mode = MODE_SILK_ONLY;
+   }
+   return mode;
+}
+
+static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_res *pcm, int frame_size, int decode_fec ARG_QEXT(opus_extension_data *ext))
+{
+   void *silk_dec;
+   CELTDecoder *celt_dec;
+   int i, silk_ret=0, celt_ret=0;
+   ec_dec dec;
+   opus_int32 silk_frame_size;
+   int pcm_transition_silk_size;
+   VARDECL(opus_res, pcm_transition_silk);
+   int pcm_transition_celt_size;
+   VARDECL(opus_res, pcm_transition_celt);
+   opus_res *pcm_transition=NULL;
+   int redundant_audio_size;
+   VARDECL(opus_res, redundant_audio);
+
+   int audiosize;
+   int mode;
+   int bandwidth;
+   int transition=0;
+   int start_band;
+   int redundancy=0;
+   int redundancy_bytes = 0;
+   int celt_to_silk=0;
+   int c;
+   int F2_5, F5, F10, F20;
+   const celt_coef *window;
+   opus_uint32 redundant_rng = 0;
+   int celt_accum;
+   ALLOC_STACK;
+
+   silk_dec = (char*)st+st->silk_dec_offset;
+   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+   F20 = st->Fs/50;
+   F10 = F20>>1;
+   F5 = F10>>1;
+   F2_5 = F5>>1;
+   if (frame_size < F2_5)
+   {
+      RESTORE_STACK;
+      return OPUS_BUFFER_TOO_SMALL;
+   }
+   /* Limit frame_size to avoid excessive stack allocations. */
+   frame_size = IMIN(frame_size, st->Fs/25*3);
+   /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
+   if (len<=1)
+   {
+      data = NULL;
+      /* In that case, don't conceal more than what the ToC says */
+      frame_size = IMIN(frame_size, st->frame_size);
+   }
+   if (data != NULL)
+   {
+      audiosize = st->frame_size;
+      mode = st->mode;
+      bandwidth = st->bandwidth;
+      ec_dec_init(&dec,(unsigned char*)data,len);
+   } else {
+      audiosize = frame_size;
+      /* Run PLC using last used mode (CELT if we ended with CELT redundancy) */
+      mode = st->prev_redundancy ? MODE_CELT_ONLY : st->prev_mode;
+      bandwidth = 0;
+
+      if (mode == 0)
+      {
+         /* If we haven't got any packet yet, all we can do is return zeros */
+         for (i=0;i<audiosize*st->channels;i++)
+            pcm[i] = 0;
+         RESTORE_STACK;
+         return audiosize;
+      }
+
+      /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
+         10, or 20 (e.g. 12.5 or 30 ms). */
+      if (audiosize > F20)
+      {
+         do {
+            int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0 ARG_QEXT(NULL));
+            if (ret<0)
+            {
+               RESTORE_STACK;
+               return ret;
+            }
+            pcm += ret*st->channels;
+            audiosize -= ret;
+         } while (audiosize > 0);
+         RESTORE_STACK;
+         return frame_size;
+      } else if (audiosize < F20)
+      {
+         if (audiosize > F10)
+            audiosize = F10;
+         else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
+            audiosize = F5;
+      }
+   }
+
+   /* In fixed-point, we can tell CELT to do the accumulation on top of the
+      SILK PCM buffer. This saves some stack space. */
+   celt_accum = (mode != MODE_CELT_ONLY);
+
+   pcm_transition_silk_size = ALLOC_NONE;
+   pcm_transition_celt_size = ALLOC_NONE;
+   if (data!=NULL && st->prev_mode > 0 && (
+       (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
+    || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
+      )
+   {
+      transition = 1;
+      /* Decide where to allocate the stack memory for pcm_transition */
+      if (mode == MODE_CELT_ONLY)
+         pcm_transition_celt_size = F5*st->channels;
+      else
+         pcm_transition_silk_size = F5*st->channels;
+   }
+   ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_res);
+   if (transition && mode == MODE_CELT_ONLY)
+   {
+      pcm_transition = pcm_transition_celt;
+      opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0 ARG_QEXT(NULL));
+   }
+   if (audiosize > frame_size)
+   {
+      /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   } else {
+      frame_size = audiosize;
+   }
+
+   /* SILK processing */
+   if (mode != MODE_CELT_ONLY)
+   {
+      int lost_flag, decoded_samples;
+      opus_res *pcm_ptr;
+      int pcm_too_small;
+      int pcm_silk_size = ALLOC_NONE;
+      VARDECL(opus_res, pcm_silk);
+      pcm_too_small = (frame_size < F10);
+      if (pcm_too_small)
+         pcm_silk_size = F10*st->channels;
+      ALLOC(pcm_silk, pcm_silk_size, opus_res);
+      if (pcm_too_small)
+         pcm_ptr = pcm_silk;
+      else
+         pcm_ptr = pcm;
+
+      if (st->prev_mode==MODE_CELT_ONLY)
+         silk_ResetDecoder( silk_dec );
+
+      /* The SILK PLC cannot produce frames of less than 10 ms */
+      st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
+
+      if (data != NULL)
+      {
+        st->DecControl.nChannelsInternal = st->stream_channels;
+        if( mode == MODE_SILK_ONLY ) {
+           if( bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
+              st->DecControl.internalSampleRate = 8000;
+           } else if( bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
+              st->DecControl.internalSampleRate = 12000;
+           } else if( bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
+              st->DecControl.internalSampleRate = 16000;
+           } else {
+              st->DecControl.internalSampleRate = 16000;
+              celt_assert( 0 );
+           }
+        } else {
+           /* Hybrid mode */
+           st->DecControl.internalSampleRate = 16000;
+        }
+     }
+     st->DecControl.enable_deep_plc = st->complexity >= 5;
+#ifdef ENABLE_OSCE
+     st->DecControl.osce_method = OSCE_METHOD_NONE;
+#ifndef DISABLE_LACE
+     if (st->complexity >= 6) {st->DecControl.osce_method = OSCE_METHOD_LACE;}
+#endif
+#ifndef DISABLE_NOLACE
+     if (st->complexity >= 7) {st->DecControl.osce_method = OSCE_METHOD_NOLACE;}
+#endif
+#ifdef ENABLE_OSCE_BWE
+     if (st->complexity >= 4 && st->DecControl.enable_osce_bwe &&
+         st->Fs == 48000 && st->DecControl.internalSampleRate == 16000 &&
+         ((mode == MODE_SILK_ONLY) || (data == NULL))) {
+         /* request WB -> FB signal extension */
+         st->DecControl.osce_extended_mode = OSCE_MODE_SILK_BBWE;
+     } else {
+         /* at this point, mode can only be MODE_SILK_ONLY or MODE_HYBRID */
+         st->DecControl.osce_extended_mode = mode == MODE_SILK_ONLY ? OSCE_MODE_SILK_ONLY : OSCE_MODE_HYBRID;
+     }
+     if (st->prev_mode == MODE_CELT_ONLY) {
+         /* Update extended mode for CELT->SILK transition */
+         st->DecControl.prev_osce_extended_mode = OSCE_MODE_CELT_ONLY;
+     }
+#endif
+#endif
+
+     lost_flag = data == NULL ? 1 : 2 * !!decode_fec;
+     decoded_samples = 0;
+     do {
+        /* Call SILK decoder */
+        int first_frame = decoded_samples == 0;
+        silk_ret = silk_Decode( silk_dec, &st->DecControl,
+                                lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size,
+#ifdef ENABLE_DEEP_PLC
+                                &st->lpcnet,
+#endif
+                                st->arch );
+        if( silk_ret ) {
+           if (lost_flag) {
+              /* PLC failure should not be fatal */
+              silk_frame_size = frame_size;
+              for (i=0;i<frame_size*st->channels;i++)
+                 pcm_ptr[i] = 0;
+           } else {
+             RESTORE_STACK;
+             return OPUS_INTERNAL_ERROR;
+           }
+        }
+        pcm_ptr += silk_frame_size * st->channels;
+        decoded_samples += silk_frame_size;
+      } while( decoded_samples < frame_size );
+     if (pcm_too_small) {
+        OPUS_COPY(pcm, pcm_silk, frame_size*st->channels);
+     }
+   }
+
+   start_band = 0;
+   if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
+    && ec_tell(&dec)+17+20*(mode == MODE_HYBRID) <= 8*len)
+   {
+      /* Check if we have a redundant 0-8 kHz band */
+      if (mode == MODE_HYBRID)
+         redundancy = ec_dec_bit_logp(&dec, 12);
+      else
+         redundancy = 1;
+      if (redundancy)
+      {
+         celt_to_silk = ec_dec_bit_logp(&dec, 1);
+         /* redundancy_bytes will be at least two, in the non-hybrid
+            case due to the ec_tell() check above */
+         redundancy_bytes = mode==MODE_HYBRID ?
+               (opus_int32)ec_dec_uint(&dec, 256)+2 :
+               len-((ec_tell(&dec)+7)>>3);
+         len -= redundancy_bytes;
+         /* This is a sanity check. It should never happen for a valid
+            packet, so the exact behaviour is not normative. */
+         if (len*8 < ec_tell(&dec))
+         {
+            len = 0;
+            redundancy_bytes = 0;
+            redundancy = 0;
+         }
+         /* Shrink decoder because of raw bits */
+         dec.storage -= redundancy_bytes;
+      }
+   }
+   if (mode != MODE_CELT_ONLY)
+      start_band = 17;
+
+   if (redundancy)
+   {
+      transition = 0;
+      pcm_transition_silk_size=ALLOC_NONE;
+   }
+
+   ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_res);
+
+   if (transition && mode != MODE_CELT_ONLY)
+   {
+      pcm_transition = pcm_transition_silk;
+      opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0 ARG_QEXT(NULL));
+   }
+
+
+   if (bandwidth)
+   {
+      int endband=21;
+
+      switch(bandwidth)
+      {
+      case OPUS_BANDWIDTH_NARROWBAND:
+         endband = 13;
+         break;
+      case OPUS_BANDWIDTH_MEDIUMBAND:
+      case OPUS_BANDWIDTH_WIDEBAND:
+         endband = 17;
+         break;
+      case OPUS_BANDWIDTH_SUPERWIDEBAND:
+         endband = 19;
+         break;
+      case OPUS_BANDWIDTH_FULLBAND:
+         endband = 21;
+         break;
+      default:
+         celt_assert(0);
+         break;
+      }
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)));
+   }
+   MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)));
+
+   /* Only allocation memory for redundancy if/when needed */
+   redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
+   ALLOC(redundant_audio, redundant_audio_size, opus_res);
+
+   /* 5 ms redundant frame for CELT->SILK*/
+   if (redundancy && celt_to_silk)
+   {
+      /* If the previous frame did not use CELT (the first redundancy frame in
+         a transition from SILK may have been lost) then the CELT decoder is
+         stale at this point and the redundancy audio is not useful, however
+         the final range is still needed (for testing), so the redundancy is
+         always decoded but the decoded audio may not be used */
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+      celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
+                          redundant_audio, F5, NULL, 0);
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+   }
+
+   /* MUST be after PLC */
+   MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)));
+
+#ifdef ENABLE_OSCE_BWE
+   if (mode != MODE_SILK_ONLY && st->DecControl.osce_extended_mode != OSCE_MODE_SILK_BBWE)
+#else
+   if (mode != MODE_SILK_ONLY)
+#endif
+   {
+      int celt_frame_size = IMIN(F20, frame_size);
+      /* Make sure to discard any previous CELT state */
+      if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
+         MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+      /* Decode CELT */
+      celt_ret = celt_decode_with_ec_dred(celt_dec, decode_fec ? NULL : data,
+                                     len, pcm, celt_frame_size, &dec, celt_accum
+#ifdef ENABLE_DEEP_PLC
+                                     , &st->lpcnet
+#endif
+                                     ARG_QEXT(ext ? ext->data : NULL) ARG_QEXT(ext ? ext->len : 0));
+      celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&st->rangeFinal));
+   } else {
+      unsigned char silence[2] = {0xFF, 0xFF};
+      if (!celt_accum)
+      {
+         for (i=0;i<frame_size*st->channels;i++)
+            pcm[i] = 0;
+      }
+      /* For hybrid -> SILK transitions, we let the CELT MDCT
+         do a fade-out by decoding a silence frame */
+      if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
+      {
+         MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+         celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
+      }
+      st->rangeFinal = dec.rng;
+   }
+
+   {
+      const CELTMode *celt_mode;
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)));
+      window = celt_mode->window;
+   }
+
+   /* 5 ms redundant frame for SILK->CELT */
+   if (redundancy && !celt_to_silk)
+   {
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+
+      celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
+      MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+      smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
+                  pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
+   }
+   /* 5ms redundant frame for CELT->SILK; ignore if the previous frame did not
+      use CELT (the first redundancy frame in a transition from SILK may have
+      been lost) */
+   if (redundancy && celt_to_silk && (st->prev_mode != MODE_SILK_ONLY || st->prev_redundancy))
+   {
+      for (c=0;c<st->channels;c++)
+      {
+         for (i=0;i<F2_5;i++)
+            pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
+      }
+      smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
+                  pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
+   }
+   if (transition)
+   {
+      if (audiosize >= F5)
+      {
+         for (i=0;i<st->channels*F2_5;i++)
+            pcm[i] = pcm_transition[i];
+         smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
+                     pcm+st->channels*F2_5, F2_5,
+                     st->channels, window, st->Fs);
+      } else {
+         /* Not enough time to do a clean transition, but we do it anyway
+            This will not preserve amplitude perfectly and may introduce
+            a bit of temporal aliasing, but it shouldn't be too bad and
+            that's pretty much the best we can do. In any case, generating this
+            transition it pretty silly in the first place */
+         smooth_fade(pcm_transition, pcm,
+                     pcm, F2_5,
+                     st->channels, window, st->Fs);
+      }
+   }
+
+   if(st->decode_gain)
+   {
+      opus_val32 gain;
+      gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
+      for (i=0;i<frame_size*st->channels;i++)
+      {
+         opus_val32 x;
+#ifdef ENABLE_RES24
+         x = MULT32_32_Q16(pcm[i],gain);
+#else
+         x = MULT16_32_P16(pcm[i],gain);
+#endif
+         pcm[i] = SATURATE(x, 32767);
+      }
+   }
+
+   if (len <= 1)
+      st->rangeFinal = 0;
+   else
+      st->rangeFinal ^= redundant_rng;
+
+   st->prev_mode = mode;
+   st->prev_redundancy = redundancy && !celt_to_silk;
+
+   if (celt_ret>=0)
+   {
+      if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
+         OPUS_PRINT_INT(audiosize);
+   }
+
+   RESTORE_STACK;
+   return celt_ret < 0 ? celt_ret : audiosize;
+
+}
+
+int opus_decode_native(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_res *pcm, int frame_size, int decode_fec,
+      int self_delimited, opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset)
+{
+   int i, nb_samples;
+   int count, offset;
+   unsigned char toc;
+   int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
+   /* 48 x 2.5 ms = 120 ms */
+   opus_int16 size[48];
+   const unsigned char *padding;
+   opus_int32 padding_len;
+   OpusExtensionIterator iter;
+   VALIDATE_OPUS_DECODER(st);
+   if (decode_fec<0 || decode_fec>1)
+      return OPUS_BAD_ARG;
+   /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
+   if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
+      return OPUS_BAD_ARG;
+#ifdef ENABLE_DRED
+   if (dred != NULL && dred->process_stage == 2) {
+      int F10;
+      int features_per_frame;
+      int needed_feature_frames;
+      int init_frames;
+      lpcnet_plc_fec_clear(&st->lpcnet);
+      F10 = st->Fs/100;
+      /* if blend==0, the last PLC call was "update" and we need to feed two extra 10-ms frames. */
+      init_frames = (st->lpcnet.blend == 0) ? 2 : 0;
+      features_per_frame = IMAX(1, frame_size/F10);
+      needed_feature_frames = init_frames + features_per_frame;
+      for (i=0;i<needed_feature_frames;i++) {
+         int feature_offset;
+         /* We floor instead of rounding because 5-ms overlap compensates for the missing 0.5 rounding offset. */
+         feature_offset = init_frames - i - 2 + (int)floor(((float)dred_offset + dred->dred_offset*F10/4)/F10);
+         if (feature_offset <= 4*dred->nb_latents-1 && feature_offset >= 0) {
+           lpcnet_plc_fec_add(&st->lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
+         } else {
+           if (feature_offset >= 0) lpcnet_plc_fec_add(&st->lpcnet, NULL);
+         }
+
+      }
+   }
+#else
+   (void)dred;
+   (void)dred_offset;
+#endif
+   if (len==0 || data==NULL)
+   {
+      int pcm_count=0;
+      do {
+         int ret;
+         ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0 ARG_QEXT(NULL));
+         if (ret<0)
+            return ret;
+         pcm_count += ret;
+      } while (pcm_count < frame_size);
+      celt_assert(pcm_count == frame_size);
+      if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels))
+         OPUS_PRINT_INT(pcm_count);
+      st->last_packet_duration = pcm_count;
+      return pcm_count;
+   } else if (len<0)
+      return OPUS_BAD_ARG;
+
+   packet_mode = opus_packet_get_mode(data);
+   packet_bandwidth = opus_packet_get_bandwidth(data);
+   packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
+   packet_stream_channels = opus_packet_get_nb_channels(data);
+
+   count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
+                                  size, &offset, packet_offset, &padding, &padding_len);
+   if (st->ignore_extensions) {
+      padding = NULL;
+      padding_len = 0;
+   }
+   if (count<0)
+      return count;
+   opus_extension_iterator_init(&iter, padding, padding_len, count);
+
+   data += offset;
+
+   if (decode_fec)
+   {
+      int duration_copy;
+      int ret;
+      /* If no FEC can be present, run the PLC (recursive call) */
+      if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
+         return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip, NULL, 0);
+      /* Otherwise, run the PLC on everything except the size for which we might have FEC */
+      duration_copy = st->last_packet_duration;
+      if (frame_size-packet_frame_size!=0)
+      {
+         ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip, NULL, 0);
+         if (ret<0)
+         {
+            st->last_packet_duration = duration_copy;
+            return ret;
+         }
+         celt_assert(ret==frame_size-packet_frame_size);
+      }
+      /* Complete with FEC */
+      st->mode = packet_mode;
+      st->bandwidth = packet_bandwidth;
+      st->frame_size = packet_frame_size;
+      st->stream_channels = packet_stream_channels;
+      ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
+            packet_frame_size, 1 ARG_QEXT(NULL));
+      if (ret<0)
+         return ret;
+      else {
+         if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels))
+            OPUS_PRINT_INT(frame_size);
+         st->last_packet_duration = frame_size;
+         return frame_size;
+      }
+   }
+
+   if (count*packet_frame_size > frame_size)
+      return OPUS_BUFFER_TOO_SMALL;
+
+   /* Update the state as the last step to avoid updating it on an invalid packet */
+   st->mode = packet_mode;
+   st->bandwidth = packet_bandwidth;
+   st->frame_size = packet_frame_size;
+   st->stream_channels = packet_stream_channels;
+
+   nb_samples=0;
+   for (i=0;i<count;i++)
+   {
+      int ret;
+#ifdef ENABLE_QEXT
+      opus_extension_data ext;
+      ext.frame = -1;
+      ext.data = NULL;
+      ext.len = 0;
+      ext.id = -1;
+      while (ext.frame < i) {
+         OpusExtensionIterator iter_copy;
+         iter_copy = iter;
+         ret = opus_extension_iterator_find(&iter, &ext, QEXT_EXTENSION_ID);
+         if (ret <= 0) break;
+         if (ext.frame > i) iter = iter_copy;
+      }
+      if (ext.frame != i) ext.data = NULL;
+#endif
+      ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0 ARG_QEXT(&ext));
+      if (ret<0)
+         return ret;
+      celt_assert(ret==packet_frame_size);
+      data += size[i];
+      nb_samples += ret;
+   }
+   st->last_packet_duration = nb_samples;
+   if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
+      OPUS_PRINT_INT(nb_samples);
+#ifndef FIXED_POINT
+   if (soft_clip)
+      opus_pcm_soft_clip_impl(pcm, nb_samples, st->channels, st->softclip_mem, st->arch);
+   else
+      st->softclip_mem[0]=st->softclip_mem[1]=0;
+#endif
+   return nb_samples;
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+   if(frame_size<=0)
+      return OPUS_BAD_ARG;
+   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+#else
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+       VARDECL(opus_res, out);
+       int ret;
+       int nb_samples;
+       ALLOC_STACK;
+
+       if(frame_size<=0)
+       {
+          RESTORE_STACK;
+          return OPUS_BAD_ARG;
+       }
+       if (data != NULL && len > 0 && !decode_fec)
+       {
+          nb_samples = opus_decoder_get_nb_samples(st, data, len);
+          if (nb_samples>0)
+             frame_size = IMIN(frame_size, nb_samples);
+          else
+             return OPUS_INVALID_PACKET;
+       }
+       celt_assert(st->channels == 1 || st->channels == 2);
+       ALLOC(out, frame_size*st->channels, opus_res);
+
+       ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, OPTIONAL_CLIP, NULL, 0);
+       if (ret > 0)
+       {
+# if defined(FIXED_POINT)
+          int i;
+          for (i=0;i<ret*st->channels;i++)
+             pcm[i] = RES2INT16(out[i]);
+# else
+          celt_float2int16(out, pcm, ret*st->channels, st->arch);
+# endif
+       }
+       RESTORE_STACK;
+       return ret;
+}
+#endif
+
+#if defined(FIXED_POINT) && defined(ENABLE_RES24)
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+   if(frame_size<=0)
+      return OPUS_BAD_ARG;
+   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+#else
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+       VARDECL(opus_res, out);
+       int ret, i;
+       int nb_samples;
+       ALLOC_STACK;
+
+       if(frame_size<=0)
+       {
+          RESTORE_STACK;
+          return OPUS_BAD_ARG;
+       }
+       if (data != NULL && len > 0 && !decode_fec)
+       {
+          nb_samples = opus_decoder_get_nb_samples(st, data, len);
+          if (nb_samples>0)
+             frame_size = IMIN(frame_size, nb_samples);
+          else
+             return OPUS_INVALID_PACKET;
+       }
+       celt_assert(st->channels == 1 || st->channels == 2);
+       ALLOC(out, frame_size*st->channels, opus_res);
+
+       ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+       if (ret > 0)
+       {
+          nb_samples = ret*st->channels;
+          for (i=0;i<nb_samples;i++)
+             pcm[i] = RES2INT24(out[i]);
+       }
+       RESTORE_STACK;
+       return ret;
+}
+#endif
+
+
+#ifndef DISABLE_FLOAT_API
+
+# if !defined(FIXED_POINT)
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
+{
+   if(frame_size<=0)
+      return OPUS_BAD_ARG;
+   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+# else
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+   VARDECL(opus_res, out);
+   int ret, i;
+   int nb_samples;
+   ALLOC_STACK;
+
+   if(frame_size<=0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   if (data != NULL && len > 0 && !decode_fec)
+   {
+      nb_samples = opus_decoder_get_nb_samples(st, data, len);
+      if (nb_samples>0)
+         frame_size = IMIN(frame_size, nb_samples);
+      else
+         return OPUS_INVALID_PACKET;
+   }
+   celt_assert(st->channels == 1 || st->channels == 2);
+   ALLOC(out, frame_size*st->channels, opus_res);
+
+   ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = RES2FLOAT(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+}
+# endif
+
+#endif
+
+
+int opus_decoder_ctl(OpusDecoder *st, int request, ...)
+{
+   int ret = OPUS_OK;
+   va_list ap;
+   void *silk_dec;
+   CELTDecoder *celt_dec;
+
+   silk_dec = (char*)st+st->silk_dec_offset;
+   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+
+
+   va_start(ap, request);
+
+   switch (request)
+   {
+   case OPUS_GET_BANDWIDTH_REQUEST:
+   {
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      *value = st->bandwidth;
+   }
+   break;
+   case OPUS_SET_COMPLEXITY_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>10)
+       {
+          goto bad_arg;
+       }
+       st->complexity = value;
+       celt_decoder_ctl(celt_dec, OPUS_SET_COMPLEXITY(value));
+   }
+   break;
+   case OPUS_GET_COMPLEXITY_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       *value = st->complexity;
+   }
+   break;
+#ifdef ENABLE_OSCE_BWE
+   case OPUS_SET_OSCE_BWE_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>1)
+       {          goto bad_arg;
+       }
+       st->DecControl.enable_osce_bwe = value;
+
+      }
+   break;
+   case OPUS_GET_OSCE_BWE_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       *value = st->DecControl.enable_osce_bwe;
+   }
+   break;
+#endif
+   case OPUS_GET_FINAL_RANGE_REQUEST:
+   {
+      opus_uint32 *value = va_arg(ap, opus_uint32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      *value = st->rangeFinal;
+   }
+   break;
+   case OPUS_RESET_STATE:
+   {
+      OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
+            sizeof(OpusDecoder)-
+            ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
+
+      celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
+      silk_ResetDecoder( silk_dec );
+      st->stream_channels = st->channels;
+      st->frame_size = st->Fs/400;
+#ifdef ENABLE_DEEP_PLC
+      lpcnet_plc_reset( &st->lpcnet );
+#endif
+   }
+   break;
+   case OPUS_GET_SAMPLE_RATE_REQUEST:
+   {
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      *value = st->Fs;
+   }
+   break;
+   case OPUS_GET_PITCH_REQUEST:
+   {
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      if (st->prev_mode == MODE_CELT_ONLY)
+         ret = celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
+      else
+         *value = st->DecControl.prevPitchLag;
+   }
+   break;
+   case OPUS_GET_GAIN_REQUEST:
+   {
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      *value = st->decode_gain;
+   }
+   break;
+   case OPUS_SET_GAIN_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if (value<-32768 || value>32767)
+       {
+          goto bad_arg;
+       }
+       st->decode_gain = value;
+   }
+   break;
+   case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+   {
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value)
+      {
+         goto bad_arg;
+      }
+      *value = st->last_packet_duration;
+   }
+   break;
+   case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>1)
+       {
+          goto bad_arg;
+       }
+       ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
+   case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
+   case OPUS_SET_IGNORE_EXTENSIONS_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>1)
+       {
+          goto bad_arg;
+       }
+       st->ignore_extensions = value;
+   }
+   break;
+   case OPUS_GET_IGNORE_EXTENSIONS_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       *value = st->ignore_extensions;
+   }
+   break;
+#ifdef USE_WEIGHTS_FILE
+   case OPUS_SET_DNN_BLOB_REQUEST:
+   {
+       const unsigned char *data = va_arg(ap, const unsigned char *);
+       opus_int32 len = va_arg(ap, opus_int32);
+       if(len<0 || data == NULL)
+       {
+          goto bad_arg;
+       }
+       ret = lpcnet_plc_load_model(&st->lpcnet, data, len);
+       ret = silk_LoadOSCEModels(silk_dec, data, len) || ret;
+   }
+   break;
+#endif
+   default:
+      /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
+      ret = OPUS_UNIMPLEMENTED;
+      break;
+   }
+
+   va_end(ap);
+   return ret;
+bad_arg:
+   va_end(ap);
+   return OPUS_BAD_ARG;
+}
+
+void opus_decoder_destroy(OpusDecoder *st)
+{
+   opus_free(st);
+}
+
+
+int opus_packet_get_bandwidth(const unsigned char *data)
+{
+   int bandwidth;
+   if (data[0]&0x80)
+   {
+      bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
+      if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
+         bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+   } else if ((data[0]&0x60) == 0x60)
+   {
+      bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND :
+                                   OPUS_BANDWIDTH_SUPERWIDEBAND;
+   } else {
+      bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
+   }
+   return bandwidth;
+}
+
+int opus_packet_get_nb_channels(const unsigned char *data)
+{
+   return (data[0]&0x4) ? 2 : 1;
+}
+
+int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
+{
+   int count;
+   if (len<1)
+      return OPUS_BAD_ARG;
+   count = packet[0]&0x3;
+   if (count==0)
+      return 1;
+   else if (count!=3)
+      return 2;
+   else if (len<2)
+      return OPUS_INVALID_PACKET;
+   else
+      return packet[1]&0x3F;
+}
+
+int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
+      opus_int32 Fs)
+{
+   int samples;
+   int count = opus_packet_get_nb_frames(packet, len);
+
+   if (count<0)
+      return count;
+
+   samples = count*opus_packet_get_samples_per_frame(packet, Fs);
+   /* Can't have more than 120 ms */
+   if (samples*25 > Fs*3)
+      return OPUS_INVALID_PACKET;
+   else
+      return samples;
+}
+
+int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len)
+{
+   int ret;
+   const unsigned char *frames[48];
+   opus_int16 size[48];
+   int packet_mode, packet_frame_size, packet_stream_channels;
+   int nb_frames=1;
+   int lbrr;
+
+   packet_mode = opus_packet_get_mode(packet);
+   if (packet_mode == MODE_CELT_ONLY)
+      return 0;
+   packet_frame_size = opus_packet_get_samples_per_frame(packet, 48000);
+   if (packet_frame_size > 960)
+      nb_frames = packet_frame_size/960;
+   packet_stream_channels = opus_packet_get_nb_channels(packet);
+   ret = opus_packet_parse(packet, len, NULL, frames, size, NULL);
+   if (ret <= 0)
+      return ret;
+   if (size[0] == 0)
+      return 0;
+   lbrr = (frames[0][0] >> (7-nb_frames)) & 0x1;
+   if (packet_stream_channels == 2)
+      lbrr = lbrr || ((frames[0][0] >> (6-2*nb_frames)) & 0x1);
+   return lbrr;
+}
+
+int opus_decoder_get_nb_samples(const OpusDecoder *dec,
+      const unsigned char packet[], opus_int32 len)
+{
+   return opus_packet_get_nb_samples(packet, len, dec->Fs);
+}
+
+struct OpusDREDDecoder {
+#ifdef ENABLE_DRED
+   RDOVAEDec model;
+#endif
+   int loaded;
+   int arch;
+   opus_uint32 magic;
+};
+
+#if defined(ENABLE_DRED) && (defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS))
+static void validate_dred_decoder(OpusDREDDecoder *st)
+{
+   celt_assert(st->magic == 0xD8EDDEC0);
+#ifdef OPUS_ARCHMASK
+   celt_assert(st->arch >= 0);
+   celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+}
+#define VALIDATE_DRED_DECODER(st) validate_dred_decoder(st)
+#else
+#define VALIDATE_DRED_DECODER(st)
+#endif
+
+
+int opus_dred_decoder_get_size(void)
+{
+  return sizeof(OpusDREDDecoder);
+}
+
+#ifdef ENABLE_DRED
+int dred_decoder_load_model(OpusDREDDecoder *dec, const unsigned char *data, int len)
+{
+    WeightArray *list;
+    int ret;
+    parse_weights(&list, data, len);
+    ret = init_rdovaedec(&dec->model, list);
+    opus_free(list);
+    if (ret == 0) dec->loaded = 1;
+    return (ret == 0) ? OPUS_OK : OPUS_BAD_ARG;
+}
+#endif
+
+int opus_dred_decoder_init(OpusDREDDecoder *dec)
+{
+   int ret = 0;
+   dec->loaded = 0;
+#if defined(ENABLE_DRED) && !defined(USE_WEIGHTS_FILE)
+   ret = init_rdovaedec(&dec->model, rdovaedec_arrays);
+   if (ret == 0) dec->loaded = 1;
+#endif
+   dec->arch = opus_select_arch();
+   /* To make sure nobody forgets to init, use a magic number. */
+   dec->magic = 0xD8EDDEC0;
+   return (ret == 0) ? OPUS_OK : OPUS_UNIMPLEMENTED;
+}
+
+OpusDREDDecoder *opus_dred_decoder_create(int *error)
+{
+   int ret;
+   OpusDREDDecoder *dec;
+   dec = (OpusDREDDecoder *)opus_alloc(opus_dred_decoder_get_size());
+   if (dec == NULL)
+   {
+      if (error)
+         *error = OPUS_ALLOC_FAIL;
+      return NULL;
+   }
+   ret = opus_dred_decoder_init(dec);
+   if (error)
+      *error = ret;
+   if (ret != OPUS_OK)
+   {
+      opus_free(dec);
+      dec = NULL;
+   }
+   return dec;
+}
+
+void opus_dred_decoder_destroy(OpusDREDDecoder *dec)
+{
+   if (dec) dec->magic = 0xDE57801D;
+   opus_free(dec);
+}
+
+int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...)
+{
+#ifdef ENABLE_DRED
+   int ret = OPUS_OK;
+   va_list ap;
+
+   va_start(ap, request);
+   (void)dred_dec;
+   switch (request)
+   {
+# ifdef USE_WEIGHTS_FILE
+   case OPUS_SET_DNN_BLOB_REQUEST:
+   {
+      const unsigned char *data = va_arg(ap, const unsigned char *);
+      opus_int32 len = va_arg(ap, opus_int32);
+      if(len<0 || data == NULL)
+      {
+         goto bad_arg;
+      }
+      return dred_decoder_load_model(dred_dec, data, len);
+   }
+   break;
+# endif
+   default:
+     /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
+     ret = OPUS_UNIMPLEMENTED;
+     break;
+  }
+  va_end(ap);
+  return ret;
+# ifdef USE_WEIGHTS_FILE
+bad_arg:
+  va_end(ap);
+  return OPUS_BAD_ARG;
+# endif
+#else
+  (void)dred_dec;
+  (void)request;
+  return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+#ifdef ENABLE_DRED
+static int dred_find_payload(const unsigned char *data, opus_int32 len, const unsigned char **payload, int *dred_frame_offset)
+{
+   OpusExtensionIterator iter;
+   opus_extension_data ext;
+   const unsigned char *padding;
+   opus_int32 padding_len;
+   int nb_frames;
+   const unsigned char *frames[48];
+   opus_int16 size[48];
+   int frame_size;
+   int ret;
+
+   *payload = NULL;
+   /* Get the padding section of the packet. */
+   ret = opus_packet_parse_impl(data, len, 0, NULL, frames, size, NULL, NULL,
+    &padding, &padding_len);
+   if (ret < 0)
+      return ret;
+   nb_frames = ret;
+   frame_size = opus_packet_get_samples_per_frame(data, 48000);
+   opus_extension_iterator_init(&iter, padding, padding_len, nb_frames);
+   for (;;) {
+      ret = opus_extension_iterator_find(&iter, &ext, DRED_EXTENSION_ID);
+      if (ret <= 0)
+         return ret;
+      /* DRED position in the packet, in units of 2.5 ms like for the signaled DRED offset. */
+      *dred_frame_offset = ext.frame*frame_size/120;
+#ifdef DRED_EXPERIMENTAL_VERSION
+      /* Check that temporary extension type and version match.
+         This check will be removed once extension is finalized. */
+      if (ext.len > DRED_EXPERIMENTAL_BYTES && ext.data[0] == 'D'
+       && ext.data[1] == DRED_EXPERIMENTAL_VERSION) {
+         *payload = ext.data+2;
+         return ext.len-2;
+      }
+#else
+      if (ext.len > 0) {
+         *payload = ext.data;
+         return ext.len;
+      }
+#endif
+   }
+}
+#endif
+
+int opus_dred_get_size(void)
+{
+#ifdef ENABLE_DRED
+  return sizeof(OpusDRED);
+#else
+  return 0;
+#endif
+}
+
+OpusDRED *opus_dred_alloc(int *error)
+{
+#ifdef ENABLE_DRED
+  OpusDRED *dec;
+  dec = (OpusDRED *)opus_alloc(opus_dred_get_size());
+  if (dec == NULL)
+  {
+    if (error)
+      *error = OPUS_ALLOC_FAIL;
+    return NULL;
+  }
+  return dec;
+#else
+  if (error)
+    *error = OPUS_UNIMPLEMENTED;
+  return NULL;
+#endif
+}
+
+void opus_dred_free(OpusDRED *dec)
+{
+#ifdef ENABLE_DRED
+  opus_free(dec);
+#else
+  (void)dec;
+#endif
+}
+
+int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing)
+{
+#ifdef ENABLE_DRED
+   const unsigned char *payload;
+   opus_int32 payload_len;
+   int dred_frame_offset=0;
+   VALIDATE_DRED_DECODER(dred_dec);
+   if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
+   dred->process_stage = -1;
+   payload_len = dred_find_payload(data, len, &payload, &dred_frame_offset);
+   if (payload_len < 0)
+      return payload_len;
+   if (payload != NULL)
+   {
+      int offset;
+      int min_feature_frames;
+      offset = 100*max_dred_samples/sampling_rate;
+      min_feature_frames = IMIN(2 + offset, 2*DRED_NUM_REDUNDANCY_FRAMES);
+      dred_ec_decode(dred, payload, payload_len, min_feature_frames, dred_frame_offset);
+      if (!defer_processing)
+         opus_dred_process(dred_dec, dred, dred);
+      if (dred_end) *dred_end = IMAX(0, -dred->dred_offset*sampling_rate/400);
+      return IMAX(0, dred->nb_latents*sampling_rate/25 - dred->dred_offset* sampling_rate/400);
+   }
+   if (dred_end) *dred_end = 0;
+   return 0;
+#else
+   (void)dred_dec;
+   (void)dred;
+   (void)data;
+   (void)len;
+   (void)max_dred_samples;
+   (void)sampling_rate;
+   (void)defer_processing;
+   (void)dred_end;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst)
+{
+#ifdef ENABLE_DRED
+   if (dred_dec == NULL || src == NULL || dst == NULL || (src->process_stage != 1 && src->process_stage != 2))
+      return OPUS_BAD_ARG;
+   VALIDATE_DRED_DECODER(dred_dec);
+   if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
+   if (src != dst)
+      OPUS_COPY(dst, src, 1);
+   if (dst->process_stage == 2)
+      return OPUS_OK;
+   DRED_rdovae_decode_all(&dred_dec->model, dst->fec_features, dst->state, dst->latents, dst->nb_latents, dred_dec->arch);
+   dst->process_stage = 2;
+   return OPUS_OK;
+#else
+   (void)dred_dec;
+   (void)src;
+   (void)dst;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+   VARDECL(float, out);
+   int ret, i;
+   ALLOC_STACK;
+
+   if(frame_size<=0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+
+   celt_assert(st->channels == 1 || st->channels == 2);
+   ALLOC(out, frame_size*st->channels, float);
+
+   ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = RES2INT16(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+#else
+   (void)st;
+   (void)dred;
+   (void)dred_offset;
+   (void)pcm;
+   (void)frame_size;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+   VARDECL(float, out);
+   int ret, i;
+   ALLOC_STACK;
+
+   if(frame_size<=0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+
+   celt_assert(st->channels == 1 || st->channels == 2);
+   ALLOC(out, frame_size*st->channels, float);
+
+   ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = RES2INT24(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+#else
+   (void)st;
+   (void)dred;
+   (void)dred_offset;
+   (void)pcm;
+   (void)frame_size;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+   if(frame_size<=0)
+      return OPUS_BAD_ARG;
+   return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, 0, dred, dred_offset);
+#else
+   (void)st;
+   (void)dred;
+   (void)dred_offset;
+   (void)pcm;
+   (void)frame_size;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_multistream_decoder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_multistream_decoder.c
new file mode 100644 (file)
index 0000000..121b33a
--- /dev/null
@@ -0,0 +1,565 @@
+/* Copyright (c) 2011 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus_multistream.h"
+#include "opus.h"
+#include "opus_private.h"
+#include "stack_alloc.h"
+#include <stdarg.h>
+#include "float_cast.h"
+#include "os_support.h"
+
+/* DECODER */
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_ms_decoder(OpusMSDecoder *st)
+{
+   validate_layout(&st->layout);
+}
+#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
+#else
+#define VALIDATE_MS_DECODER(st)
+#endif
+
+
+opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
+{
+   int coupled_size;
+   int mono_size;
+
+   if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
+   coupled_size = opus_decoder_get_size(2);
+   mono_size = opus_decoder_get_size(1);
+   return align(sizeof(OpusMSDecoder))
+         + nb_coupled_streams * align(coupled_size)
+         + (nb_streams-nb_coupled_streams) * align(mono_size);
+}
+
+int opus_multistream_decoder_init(
+      OpusMSDecoder *st,
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping
+)
+{
+   int coupled_size;
+   int mono_size;
+   int i, ret;
+   char *ptr;
+
+   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+       (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
+      return OPUS_BAD_ARG;
+
+   st->layout.nb_channels = channels;
+   st->layout.nb_streams = streams;
+   st->layout.nb_coupled_streams = coupled_streams;
+
+   for (i=0;i<st->layout.nb_channels;i++)
+      st->layout.mapping[i] = mapping[i];
+   if (!validate_layout(&st->layout))
+      return OPUS_BAD_ARG;
+
+   ptr = (char*)st + align(sizeof(OpusMSDecoder));
+   coupled_size = opus_decoder_get_size(2);
+   mono_size = opus_decoder_get_size(1);
+
+   for (i=0;i<st->layout.nb_coupled_streams;i++)
+   {
+      ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
+      if(ret!=OPUS_OK)return ret;
+      ptr += align(coupled_size);
+   }
+   for (;i<st->layout.nb_streams;i++)
+   {
+      ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
+      if(ret!=OPUS_OK)return ret;
+      ptr += align(mono_size);
+   }
+   return OPUS_OK;
+}
+
+
+OpusMSDecoder *opus_multistream_decoder_create(
+      opus_int32 Fs,
+      int channels,
+      int streams,
+      int coupled_streams,
+      const unsigned char *mapping,
+      int *error
+)
+{
+   int ret;
+   OpusMSDecoder *st;
+   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+       (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
+   {
+      if (error)
+         *error = OPUS_BAD_ARG;
+      return NULL;
+   }
+   st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
+   if (st==NULL)
+   {
+      if (error)
+         *error = OPUS_ALLOC_FAIL;
+      return NULL;
+   }
+   ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
+   if (error)
+      *error = ret;
+   if (ret != OPUS_OK)
+   {
+      opus_free(st);
+      st = NULL;
+   }
+   return st;
+}
+
+static int opus_multistream_packet_validate(const unsigned char *data,
+      opus_int32 len, int nb_streams, opus_int32 Fs)
+{
+   int s;
+   int count;
+   unsigned char toc;
+   opus_int16 size[48];
+   int samples=0;
+   opus_int32 packet_offset;
+
+   for (s=0;s<nb_streams;s++)
+   {
+      int tmp_samples;
+      if (len<=0)
+         return OPUS_INVALID_PACKET;
+      count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
+                                     size, NULL, &packet_offset, NULL, NULL);
+      if (count<0)
+         return count;
+      tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
+      if (s!=0 && samples != tmp_samples)
+         return OPUS_INVALID_PACKET;
+      samples = tmp_samples;
+      data += packet_offset;
+      len -= packet_offset;
+   }
+   return samples;
+}
+
+int opus_multistream_decode_native(
+      OpusMSDecoder *st,
+      const unsigned char *data,
+      opus_int32 len,
+      void *pcm,
+      opus_copy_channel_out_func copy_channel_out,
+      int frame_size,
+      int decode_fec,
+      int soft_clip,
+      void *user_data
+)
+{
+   opus_int32 Fs;
+   int coupled_size;
+   int mono_size;
+   int s, c;
+   char *ptr;
+   int do_plc=0;
+   VARDECL(opus_res, buf);
+   ALLOC_STACK;
+
+   VALIDATE_MS_DECODER(st);
+   if (frame_size <= 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   /* Limit frame_size to avoid excessive stack allocations. */
+   MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
+   frame_size = IMIN(frame_size, Fs/25*3);
+   ALLOC(buf, 2*frame_size, opus_res);
+   ptr = (char*)st + align(sizeof(OpusMSDecoder));
+   coupled_size = opus_decoder_get_size(2);
+   mono_size = opus_decoder_get_size(1);
+
+   if (len==0)
+      do_plc = 1;
+   if (len < 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   if (!do_plc && len < 2*st->layout.nb_streams-1)
+   {
+      RESTORE_STACK;
+      return OPUS_INVALID_PACKET;
+   }
+   if (!do_plc)
+   {
+      int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
+      if (ret < 0)
+      {
+         RESTORE_STACK;
+         return ret;
+      } else if (ret > frame_size)
+      {
+         RESTORE_STACK;
+         return OPUS_BUFFER_TOO_SMALL;
+      }
+   }
+   for (s=0;s<st->layout.nb_streams;s++)
+   {
+      OpusDecoder *dec;
+      opus_int32 packet_offset;
+      int ret;
+
+      dec = (OpusDecoder*)ptr;
+      ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
+
+      if (!do_plc && len<=0)
+      {
+         RESTORE_STACK;
+         return OPUS_INTERNAL_ERROR;
+      }
+      packet_offset = 0;
+      ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip, NULL, 0);
+      if (!do_plc)
+      {
+        data += packet_offset;
+        len -= packet_offset;
+      }
+      if (ret <= 0)
+      {
+         RESTORE_STACK;
+         return ret;
+      }
+      frame_size = ret;
+      if (s < st->layout.nb_coupled_streams)
+      {
+         int chan, prev;
+         prev = -1;
+         /* Copy "left" audio to the channel(s) where it belongs */
+         while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
+         {
+            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+               buf, 2, frame_size, user_data);
+            prev = chan;
+         }
+         prev = -1;
+         /* Copy "right" audio to the channel(s) where it belongs */
+         while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
+         {
+            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+               buf+1, 2, frame_size, user_data);
+            prev = chan;
+         }
+      } else {
+         int chan, prev;
+         prev = -1;
+         /* Copy audio to the channel(s) where it belongs */
+         while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
+         {
+            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+               buf, 1, frame_size, user_data);
+            prev = chan;
+         }
+      }
+   }
+   /* Handle muted channels */
+   for (c=0;c<st->layout.nb_channels;c++)
+   {
+      if (st->layout.mapping[c] == 255)
+      {
+         (*copy_channel_out)(pcm, st->layout.nb_channels, c,
+            NULL, 0, frame_size, user_data);
+      }
+   }
+   RESTORE_STACK;
+   return frame_size;
+}
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_copy_channel_out_float(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data
+)
+{
+   float *float_dst;
+   opus_int32 i;
+   (void)user_data;
+   float_dst = (float*)dst;
+   if (src != NULL)
+   {
+      for (i=0;i<frame_size;i++)
+         float_dst[i*dst_stride+dst_channel] = RES2FLOAT(src[i*src_stride]);
+   }
+   else
+   {
+      for (i=0;i<frame_size;i++)
+         float_dst[i*dst_stride+dst_channel] = 0;
+   }
+}
+#endif
+
+static void opus_copy_channel_out_short(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data
+)
+{
+   opus_int16 *short_dst;
+   opus_int32 i;
+   (void)user_data;
+   short_dst = (opus_int16*)dst;
+   if (src != NULL)
+   {
+      for (i=0;i<frame_size;i++)
+         short_dst[i*dst_stride+dst_channel] = RES2INT16(src[i*src_stride]);
+   }
+   else
+   {
+      for (i=0;i<frame_size;i++)
+         short_dst[i*dst_stride+dst_channel] = 0;
+   }
+}
+
+static void opus_copy_channel_out_int24(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data
+)
+{
+   opus_int32 *short_dst;
+   opus_int32 i;
+   (void)user_data;
+   short_dst = (opus_int32*)dst;
+   if (src != NULL)
+   {
+      for (i=0;i<frame_size;i++)
+         short_dst[i*dst_stride+dst_channel] = RES2INT24(src[i*src_stride]);
+   }
+   else
+   {
+      for (i=0;i<frame_size;i++)
+         short_dst[i*dst_stride+dst_channel] = 0;
+   }
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+int opus_multistream_decode(
+      OpusMSDecoder *st,
+      const unsigned char *data,
+      opus_int32 len,
+      opus_int16 *pcm,
+      int frame_size,
+      int decode_fec
+)
+{
+   return opus_multistream_decode_native(st, data, len,
+       pcm, opus_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP, NULL);
+}
+
+int opus_multistream_decode24(
+      OpusMSDecoder *st,
+      const unsigned char *data,
+      opus_int32 len,
+      opus_int32 *pcm,
+      int frame_size,
+      int decode_fec
+)
+{
+   return opus_multistream_decode_native(st, data, len,
+       pcm, opus_copy_channel_out_int24, frame_size, decode_fec, 0, NULL);
+}
+
+#ifndef DISABLE_FLOAT_API
+int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
+      opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+   return opus_multistream_decode_native(st, data, len,
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
+}
+#endif
+
+int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
+                                         va_list ap)
+{
+   int coupled_size, mono_size;
+   char *ptr;
+   int ret = OPUS_OK;
+
+   coupled_size = opus_decoder_get_size(2);
+   mono_size = opus_decoder_get_size(1);
+   ptr = (char*)st + align(sizeof(OpusMSDecoder));
+   switch (request)
+   {
+       case OPUS_GET_BANDWIDTH_REQUEST:
+       case OPUS_GET_SAMPLE_RATE_REQUEST:
+       case OPUS_GET_GAIN_REQUEST:
+       case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+       case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+       case OPUS_GET_COMPLEXITY_REQUEST:
+       {
+          OpusDecoder *dec;
+          /* For int32* GET params, just query the first stream */
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          dec = (OpusDecoder*)ptr;
+          ret = opus_decoder_ctl(dec, request, value);
+       }
+       break;
+       case OPUS_GET_FINAL_RANGE_REQUEST:
+       {
+          int s;
+          opus_uint32 *value = va_arg(ap, opus_uint32*);
+          opus_uint32 tmp;
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = 0;
+          for (s=0;s<st->layout.nb_streams;s++)
+          {
+             OpusDecoder *dec;
+             dec = (OpusDecoder*)ptr;
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+             ret = opus_decoder_ctl(dec, request, &tmp);
+             if (ret != OPUS_OK) break;
+             *value ^= tmp;
+          }
+       }
+       break;
+       case OPUS_RESET_STATE:
+       {
+          int s;
+          for (s=0;s<st->layout.nb_streams;s++)
+          {
+             OpusDecoder *dec;
+
+             dec = (OpusDecoder*)ptr;
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+             ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
+             if (ret != OPUS_OK)
+                break;
+          }
+       }
+       break;
+       case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
+       {
+          int s;
+          opus_int32 stream_id;
+          OpusDecoder **value;
+          stream_id = va_arg(ap, opus_int32);
+          if (stream_id<0 || stream_id >= st->layout.nb_streams)
+             goto bad_arg;
+          value = va_arg(ap, OpusDecoder**);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          for (s=0;s<stream_id;s++)
+          {
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+          }
+          *value = (OpusDecoder*)ptr;
+       }
+       break;
+       case OPUS_SET_GAIN_REQUEST:
+       case OPUS_SET_COMPLEXITY_REQUEST:
+       case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+       {
+          int s;
+          /* This works for int32 params */
+          opus_int32 value = va_arg(ap, opus_int32);
+          for (s=0;s<st->layout.nb_streams;s++)
+          {
+             OpusDecoder *dec;
+
+             dec = (OpusDecoder*)ptr;
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+             ret = opus_decoder_ctl(dec, request, value);
+             if (ret != OPUS_OK)
+                break;
+          }
+       }
+       break;
+       default:
+          ret = OPUS_UNIMPLEMENTED;
+       break;
+   }
+   return ret;
+bad_arg:
+   return OPUS_BAD_ARG;
+}
+
+int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+{
+   int ret;
+   va_list ap;
+   va_start(ap, request);
+   ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
+   va_end(ap);
+   return ret;
+}
+
+void opus_multistream_decoder_destroy(OpusMSDecoder *st)
+{
+    opus_free(st);
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_private.h b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_private.h
new file mode 100644 (file)
index 0000000..289f97f
--- /dev/null
@@ -0,0 +1,266 @@
+/* Copyright (c) 2012 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef OPUS_PRIVATE_H
+#define OPUS_PRIVATE_H
+
+#include "arch.h"
+#include "opus.h"
+#include "celt.h"
+
+#include <stdarg.h> /* va_list */
+#include <stddef.h> /* offsetof */
+
+struct OpusRepacketizer {
+   unsigned char toc;
+   int nb_frames;
+   const unsigned char *frames[48];
+   opus_int16 len[48];
+   int framesize;
+   const unsigned char *paddings[48];
+   opus_int32 padding_len[48];
+   unsigned char padding_nb_frames[48];
+};
+
+typedef struct OpusExtensionIterator {
+   const unsigned char *data;
+   const unsigned char *curr_data;
+   const unsigned char *repeat_data;
+   const unsigned char *last_long;
+   const unsigned char *src_data;
+   opus_int32 len;
+   opus_int32 curr_len;
+   opus_int32 repeat_len;
+   opus_int32 src_len;
+   opus_int32 trailing_short_len;
+   int nb_frames;
+   int frame_max;
+   int curr_frame;
+   int repeat_frame;
+   unsigned char repeat_l;
+} OpusExtensionIterator;
+
+typedef struct {
+   int id;
+   int frame;
+   const unsigned char *data;
+   opus_int32 len;
+} opus_extension_data;
+
+void opus_extension_iterator_init(OpusExtensionIterator *iter,
+ const unsigned char *data, opus_int32 len, opus_int32 nb_frames);
+
+void opus_extension_iterator_reset(OpusExtensionIterator *iter);
+void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
+ int frame_max);
+int opus_extension_iterator_next(OpusExtensionIterator *iter,
+ opus_extension_data *ext);
+int opus_extension_iterator_find(OpusExtensionIterator *iter,
+ opus_extension_data *ext, int id);
+
+typedef struct ChannelLayout {
+   int nb_channels;
+   int nb_streams;
+   int nb_coupled_streams;
+   unsigned char mapping[256];
+} ChannelLayout;
+
+typedef enum {
+  MAPPING_TYPE_NONE,
+  MAPPING_TYPE_SURROUND,
+  MAPPING_TYPE_AMBISONICS
+} MappingType;
+
+struct OpusMSEncoder {
+   ChannelLayout layout;
+   int arch;
+   int lfe_stream;
+   int application;
+   opus_int32 Fs;
+   int variable_duration;
+   MappingType mapping_type;
+   opus_int32 bitrate_bps;
+   /* Encoder states go here */
+   /* then opus_val32 window_mem[channels*120]; */
+   /* then opus_val32 preemph_mem[channels]; */
+};
+
+struct OpusMSDecoder {
+   ChannelLayout layout;
+   /* Decoder states go here */
+};
+
+int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
+  va_list ap);
+int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
+  va_list ap);
+
+int validate_layout(const ChannelLayout *layout);
+int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
+int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
+int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
+
+typedef void (*opus_copy_channel_in_func)(
+  opus_res *dst,
+  int dst_stride,
+  const void *src,
+  int src_stride,
+  int src_channel,
+  int frame_size,
+  void *user_data
+);
+
+typedef void (*opus_copy_channel_out_func)(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data
+);
+
+#define MODE_SILK_ONLY          1000
+#define MODE_HYBRID             1001
+#define MODE_CELT_ONLY          1002
+
+#define OPUS_SET_VOICE_RATIO_REQUEST         11018
+#define OPUS_GET_VOICE_RATIO_REQUEST         11019
+
+/** Configures the encoder's expected percentage of voice
+  * opposed to music or other signals.
+  *
+  * @note This interface is currently more aspiration than actuality. It's
+  * ultimately expected to bias an automatic signal classifier, but it currently
+  * just shifts the static bitrate to mode mapping around a little bit.
+  *
+  * @param[in] x <tt>int</tt>:   Voice percentage in the range 0-100, inclusive.
+  * @hideinitializer */
+#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO
+  *
+  * @param[out] x <tt>int*</tt>:  Voice percentage in the range 0-100, inclusive.
+  * @hideinitializer */
+#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, opus_check_int_ptr(x)
+
+
+#define OPUS_SET_FORCE_MODE_REQUEST    11002
+#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, opus_check_int(x)
+
+typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
+void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+void downmix_int24(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
+
+void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch);
+
+int encode_size(int size, unsigned char *data);
+
+opus_int32 frame_size_select(int application, opus_int32 frame_size, int variable_duration, opus_int32 Fs);
+
+opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
+      unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
+      const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
+      int analysis_channels, downmix_func downmix, int float_api);
+
+int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
+      opus_res *pcm, int frame_size, int decode_fec, int self_delimited,
+      opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset);
+
+/* Make sure everything is properly aligned. */
+static OPUS_INLINE int align(int i)
+{
+    struct foo {char c; union { void* p; opus_int32 i; opus_val32 v; } u;};
+
+    unsigned int alignment = offsetof(struct foo, u);
+
+    /* Optimizing compilers should optimize div and multiply into and
+       for all sensible alignment values. */
+    return ((i + alignment - 1) / alignment) * alignment;
+}
+
+int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
+      int self_delimited, unsigned char *out_toc,
+      const unsigned char *frames[48], opus_int16 size[48],
+      int *payload_offset, opus_int32 *packet_offset,
+      const unsigned char **padding, opus_int32 *padding_len);
+
+opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
+      unsigned char *data, opus_int32 maxlen, int self_delimited, int pad,
+      const opus_extension_data *extensions, int nb_extensions);
+
+int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
+
+int opus_multistream_encode_native
+(
+  struct OpusMSEncoder *st,
+  opus_copy_channel_in_func copy_channel_in,
+  const void *pcm,
+  int analysis_frame_size,
+  unsigned char *data,
+  opus_int32 max_data_bytes,
+  int lsb_depth,
+  downmix_func downmix,
+  int float_api,
+  void *user_data
+);
+
+int opus_multistream_decode_native(
+  struct OpusMSDecoder *st,
+  const unsigned char *data,
+  opus_int32 len,
+  void *pcm,
+  opus_copy_channel_out_func copy_channel_out,
+  int frame_size,
+  int decode_fec,
+  int soft_clip,
+  void *user_data
+);
+
+opus_int32 opus_packet_extensions_parse(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ int nb_frames);
+
+opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ const opus_int32 *nb_frame_exts, int nb_frames);
+
+opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
+ const opus_extension_data *extensions, opus_int32 nb_extensions,
+ int nb_frames, int pad);
+
+opus_int32 opus_packet_extensions_count(const unsigned char *data,
+ opus_int32 len, int nb_frames);
+
+opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
+ opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames);
+
+opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data  *extensions, int nb_extensions);
+
+#endif /* OPUS_PRIVATE_H */
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_projection_decoder.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/opus_projection_decoder.c
new file mode 100644 (file)
index 0000000..f490575
--- /dev/null
@@ -0,0 +1,282 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "os_support.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "opus_projection.h"
+#include "opus_multistream.h"
+#include "mapping_matrix.h"
+#include "stack_alloc.h"
+
+struct OpusProjectionDecoder
+{
+  opus_int32 demixing_matrix_size_in_bytes;
+  /* Encoder states go here */
+};
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_out_float(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data)
+{
+  float *float_dst;
+  const MappingMatrix *matrix;
+  float_dst = (float *)dst;
+  matrix = (const MappingMatrix *)user_data;
+
+  if (dst_channel == 0)
+    OPUS_CLEAR(float_dst, frame_size * dst_stride);
+
+  if (src != NULL)
+    mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
+      src_stride, float_dst, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_out_short(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data)
+{
+  opus_int16 *short_dst;
+  const MappingMatrix *matrix;
+  short_dst = (opus_int16 *)dst;
+  matrix = (const MappingMatrix *)user_data;
+  if (dst_channel == 0)
+    OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+  if (src != NULL)
+    mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
+      src_stride, short_dst, dst_stride, frame_size);
+}
+
+static void opus_projection_copy_channel_out_int24(
+  void *dst,
+  int dst_stride,
+  int dst_channel,
+  const opus_res *src,
+  int src_stride,
+  int frame_size,
+  void *user_data)
+{
+  opus_int32 *short_dst;
+  const MappingMatrix *matrix;
+  short_dst = (opus_int32 *)dst;
+  matrix = (const MappingMatrix *)user_data;
+  if (dst_channel == 0)
+    OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+  if (src != NULL)
+    mapping_matrix_multiply_channel_out_int24(matrix, src, dst_channel,
+      src_stride, short_dst, dst_stride, frame_size);
+}
+
+static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
+{
+  /* void* cast avoids clang -Wcast-align warning */
+  return (MappingMatrix*)(void*)((char*)st +
+    align(sizeof(OpusProjectionDecoder)));
+}
+
+static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
+{
+  /* void* cast avoids clang -Wcast-align warning */
+  return (OpusMSDecoder*)(void*)((char*)st +
+    align(sizeof(OpusProjectionDecoder) +
+    st->demixing_matrix_size_in_bytes));
+}
+
+opus_int32 opus_projection_decoder_get_size(int channels, int streams,
+                                            int coupled_streams)
+{
+  opus_int32 matrix_size;
+  opus_int32 decoder_size;
+
+  matrix_size =
+    mapping_matrix_get_size(streams + coupled_streams, channels);
+  if (!matrix_size)
+    return 0;
+
+  decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
+  if (!decoder_size)
+    return 0;
+
+  return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
+}
+
+int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
+  int channels, int streams, int coupled_streams,
+  unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
+{
+  int nb_input_streams;
+  opus_int32 expected_matrix_size;
+  int i, ret;
+  unsigned char mapping[255];
+  VARDECL(opus_int16, buf);
+  ALLOC_STACK;
+
+  /* Verify supplied matrix size. */
+  nb_input_streams = streams + coupled_streams;
+  expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
+  if (expected_matrix_size != demixing_matrix_size)
+  {
+    RESTORE_STACK;
+    return OPUS_BAD_ARG;
+  }
+
+  /* Convert demixing matrix input into internal format. */
+  ALLOC(buf, nb_input_streams * channels, opus_int16);
+  for (i = 0; i < nb_input_streams * channels; i++)
+  {
+    int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
+    s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
+    buf[i] = (opus_int16)s;
+  }
+
+  /* Assign demixing matrix. */
+  st->demixing_matrix_size_in_bytes =
+    mapping_matrix_get_size(channels, nb_input_streams);
+  if (!st->demixing_matrix_size_in_bytes)
+  {
+    RESTORE_STACK;
+    return OPUS_BAD_ARG;
+  }
+
+  mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
+    buf, demixing_matrix_size);
+
+  /* Set trivial mapping so each input channel pairs with a matrix column. */
+  for (i = 0; i < channels; i++)
+    mapping[i] = i;
+
+  ret = opus_multistream_decoder_init(
+    get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
+  RESTORE_STACK;
+  return ret;
+}
+
+OpusProjectionDecoder *opus_projection_decoder_create(
+  opus_int32 Fs, int channels, int streams, int coupled_streams,
+  unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
+{
+  int size;
+  int ret;
+  OpusProjectionDecoder *st;
+
+  /* Allocate space for the projection decoder. */
+  size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
+  if (!size) {
+    if (error)
+      *error = OPUS_ALLOC_FAIL;
+    return NULL;
+  }
+  st = (OpusProjectionDecoder *)opus_alloc(size);
+  if (!st)
+  {
+    if (error)
+      *error = OPUS_ALLOC_FAIL;
+    return NULL;
+  }
+
+  /* Initialize projection decoder with provided settings. */
+  ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
+                                     demixing_matrix, demixing_matrix_size);
+  if (ret != OPUS_OK)
+  {
+    opus_free(st);
+    st = NULL;
+  }
+  if (error)
+    *error = ret;
+  return st;
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
+                           opus_int32 len, opus_int16 *pcm, int frame_size,
+                           int decode_fec)
+{
+  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+    pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP,
+    get_dec_demixing_matrix(st));
+}
+
+int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
+                           opus_int32 len, opus_int32 *pcm, int frame_size,
+                           int decode_fec)
+{
+  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+    pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
+    get_dec_demixing_matrix(st));
+}
+
+#ifndef DISABLE_FLOAT_API
+int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
+                                 opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+  return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+    pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
+    get_dec_demixing_matrix(st));
+}
+#endif
+
+int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
+{
+  va_list ap;
+  int ret = OPUS_OK;
+
+  va_start(ap, request);
+  ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
+    request, ap);
+  va_end(ap);
+  return ret;
+}
+
+void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
+{
+  opus_free(st);
+}
diff --git a/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/repacketizer.c b/code/sdk/zhihui/test_opus_frame_to_pcm/src_lib/repacketizer.c
new file mode 100644 (file)
index 0000000..667176e
--- /dev/null
@@ -0,0 +1,468 @@
+/* Copyright (c) 2011 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus.h"
+#include "opus_private.h"
+#include "os_support.h"
+#include "stack_alloc.h"
+
+
+int opus_repacketizer_get_size(void)
+{
+   return sizeof(OpusRepacketizer);
+}
+
+OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
+{
+   rp->nb_frames = 0;
+   return rp;
+}
+
+OpusRepacketizer *opus_repacketizer_create(void)
+{
+   OpusRepacketizer *rp;
+   rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
+   if(rp==NULL)return NULL;
+   return opus_repacketizer_init(rp);
+}
+
+void opus_repacketizer_destroy(OpusRepacketizer *rp)
+{
+   opus_free(rp);
+}
+
+static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
+{
+   unsigned char tmp_toc;
+   int curr_nb_frames,ret;
+   /* Set of check ToC */
+   if (len<1) return OPUS_INVALID_PACKET;
+   if (rp->nb_frames == 0)
+   {
+      rp->toc = data[0];
+      rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
+   } else if ((rp->toc&0xFC) != (data[0]&0xFC))
+   {
+      /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
+      return OPUS_INVALID_PACKET;
+   }
+   curr_nb_frames = opus_packet_get_nb_frames(data, len);
+   if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
+
+   /* Check the 120 ms maximum packet size */
+   if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
+   {
+      return OPUS_INVALID_PACKET;
+   }
+
+   ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames],
+       NULL, NULL, &rp->paddings[rp->nb_frames], &rp->padding_len[rp->nb_frames]);
+   if(ret<1)return ret;
+   rp->padding_nb_frames[rp->nb_frames]=ret;
+
+   /* set padding length to zero for all but the first frame */
+   while (curr_nb_frames > 1)
+   {
+      rp->nb_frames++;
+      rp->padding_len[rp->nb_frames] = 0;
+      rp->padding_nb_frames[rp->nb_frames] = 0;
+      rp->paddings[rp->nb_frames] = NULL;
+      curr_nb_frames--;
+   }
+   rp->nb_frames++;
+   return OPUS_OK;
+}
+
+int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
+{
+   return opus_repacketizer_cat_impl(rp, data, len, 0);
+}
+
+int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
+{
+   return rp->nb_frames;
+}
+
+opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
+      unsigned char *data, opus_int32 maxlen, int self_delimited, int pad, const opus_extension_data *extensions, int nb_extensions)
+{
+   int i, count;
+   opus_int32 tot_size;
+   opus_int16 *len;
+   const unsigned char **frames;
+   unsigned char * ptr;
+   int ones_begin=0, ones_end=0;
+   int ext_begin=0, ext_len=0;
+   int ext_count, total_ext_count;
+   VARDECL(opus_extension_data, all_extensions);
+   SAVE_STACK;
+
+   if (begin<0 || begin>=end || end>rp->nb_frames)
+   {
+      /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   count = end-begin;
+
+   len = rp->len+begin;
+   frames = rp->frames+begin;
+   if (self_delimited)
+      tot_size = 1 + (len[count-1]>=252);
+   else
+      tot_size = 0;
+
+   /* figure out total number of extensions */
+   total_ext_count = nb_extensions;
+   for (i=begin;i<end;i++)
+   {
+      int n = opus_packet_extensions_count(rp->paddings[i], rp->padding_len[i],
+       rp->padding_nb_frames[i]);
+      if (n > 0) total_ext_count += n;
+   }
+   ALLOC(all_extensions, total_ext_count ? total_ext_count : ALLOC_NONE, opus_extension_data);
+   /* copy over any extensions that were passed in */
+   for (ext_count=0;ext_count<nb_extensions;ext_count++)
+   {
+      all_extensions[ext_count] = extensions[ext_count];
+   }
+
+   /* incorporate any extensions from the repacketizer padding */
+   for (i=begin;i<end;i++)
+   {
+      int j, ret;
+      opus_int32 frame_ext_count;
+      frame_ext_count = total_ext_count - ext_count;
+      ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
+         &all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]);
+      if (ret<0)
+      {
+         RESTORE_STACK;
+         return OPUS_INTERNAL_ERROR;
+      }
+      /* renumber the extension frame numbers */
+      for (j=0;j<frame_ext_count;j++)
+      {
+         all_extensions[ext_count+j].frame += i-begin;
+      }
+      ext_count += frame_ext_count;
+   }
+
+   ptr = data;
+   if (count==1)
+   {
+      /* Code 0 */
+      tot_size += len[0]+1;
+      if (tot_size > maxlen)
+      {
+         RESTORE_STACK;
+         return OPUS_BUFFER_TOO_SMALL;
+      }
+      *ptr++ = rp->toc&0xFC;
+   } else if (count==2)
+   {
+      if (len[1] == len[0])
+      {
+         /* Code 1 */
+         tot_size += 2*len[0]+1;
+         if (tot_size > maxlen)
+         {
+            RESTORE_STACK;
+            return OPUS_BUFFER_TOO_SMALL;
+         }
+         *ptr++ = (rp->toc&0xFC) | 0x1;
+      } else {
+         /* Code 2 */
+         tot_size += len[0]+len[1]+2+(len[0]>=252);
+         if (tot_size > maxlen)
+         {
+            RESTORE_STACK;
+            return OPUS_BUFFER_TOO_SMALL;
+         }
+         *ptr++ = (rp->toc&0xFC) | 0x2;
+         ptr += encode_size(len[0], ptr);
+      }
+   }
+   if (count > 2 || (pad && tot_size < maxlen) || ext_count > 0)
+   {
+      /* Code 3 */
+      int vbr;
+      int pad_amount=0;
+
+      /* Restart the process for the padding case */
+      ptr = data;
+      if (self_delimited)
+         tot_size = 1 + (len[count-1]>=252);
+      else
+         tot_size = 0;
+      vbr = 0;
+      for (i=1;i<count;i++)
+      {
+         if (len[i] != len[0])
+         {
+            vbr=1;
+            break;
+         }
+      }
+      if (vbr)
+      {
+         tot_size += 2;
+         for (i=0;i<count-1;i++)
+            tot_size += 1 + (len[i]>=252) + len[i];
+         tot_size += len[count-1];
+
+         if (tot_size > maxlen)
+         {
+            RESTORE_STACK;
+            return OPUS_BUFFER_TOO_SMALL;
+         }
+         *ptr++ = (rp->toc&0xFC) | 0x3;
+         *ptr++ = count | 0x80;
+      } else {
+         tot_size += count*len[0]+2;
+         if (tot_size > maxlen)
+         {
+            RESTORE_STACK;
+            return OPUS_BUFFER_TOO_SMALL;
+         }
+         *ptr++ = (rp->toc&0xFC) | 0x3;
+         *ptr++ = count;
+      }
+      pad_amount = pad ? (maxlen-tot_size) : 0;
+      if (ext_count>0)
+      {
+         /* figure out how much space we need for the extensions */
+         ext_len = opus_packet_extensions_generate(NULL, maxlen-tot_size,
+          all_extensions, ext_count, count, 0);
+         if (ext_len < 0) return ext_len;
+         if (!pad)
+            pad_amount = ext_len + (ext_len ? (ext_len+253)/254 : 1);
+      }
+      if (pad_amount != 0)
+      {
+         int nb_255s;
+         data[1] |= 0x40;
+         nb_255s = (pad_amount-1)/255;
+         if (tot_size + ext_len + nb_255s + 1 > maxlen)
+         {
+            RESTORE_STACK;
+            return OPUS_BUFFER_TOO_SMALL;
+         }
+         ext_begin = tot_size+pad_amount-ext_len;
+         /* Prepend 0x01 padding */
+         ones_begin = tot_size+nb_255s+1;
+         ones_end = tot_size+pad_amount-ext_len;
+         for (i=0;i<nb_255s;i++)
+            *ptr++ = 255;
+         *ptr++ = pad_amount-255*nb_255s-1;
+         tot_size += pad_amount;
+      }
+      if (vbr)
+      {
+         for (i=0;i<count-1;i++)
+            ptr += encode_size(len[i], ptr);
+      }
+   }
+   if (self_delimited) {
+      int sdlen = encode_size(len[count-1], ptr);
+      ptr += sdlen;
+   }
+   /* Copy the actual data */
+   for (i=0;i<count;i++)
+   {
+      /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
+         padding from opus_packet_pad or opus_packet_unpad(). */
+      /* assert disabled because it's not valid in C. */
+      /* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
+      OPUS_MOVE(ptr, frames[i], len[i]);
+      ptr += len[i];
+   }
+   if (ext_len > 0) {
+      int ret = opus_packet_extensions_generate(&data[ext_begin], ext_len,
+       all_extensions, ext_count, count, 0);
+      celt_assert(ret == ext_len);
+   }
+   for (i=ones_begin;i<ones_end;i++)
+      data[i] = 0x01;
+   if (pad && ext_count==0)
+   {
+      /* Fill padding with zeros. */
+      while (ptr<data+maxlen)
+         *ptr++=0;
+   }
+   RESTORE_STACK;
+   return tot_size;
+}
+
+opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
+{
+   return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0, NULL, 0);
+}
+
+opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
+{
+   return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0, NULL, 0);
+}
+
+opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data  *extensions, int nb_extensions)
+{
+   OpusRepacketizer rp;
+   opus_int32 ret;
+   VARDECL(unsigned char, copy);
+   SAVE_STACK;
+   if (len < 1)
+      return OPUS_BAD_ARG;
+   if (len==new_len)
+      return OPUS_OK;
+   else if (len > new_len)
+      return OPUS_BAD_ARG;
+   ALLOC(copy, len, unsigned char);
+   opus_repacketizer_init(&rp);
+   /* Moving payload to the end of the packet so we can do in-place padding */
+   OPUS_COPY(copy, data, len);
+   ret = opus_repacketizer_cat(&rp, copy, len);
+   if (ret != OPUS_OK)
+      return ret;
+   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, pad, extensions, nb_extensions);
+   RESTORE_STACK;
+   return ret;
+}
+
+int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
+{
+   opus_int32 ret;
+   ALLOC_STACK;
+   ret = opus_packet_pad_impl(data, len, new_len, 1, NULL, 0);
+   RESTORE_STACK;
+   if (ret > 0)
+      return OPUS_OK;
+   else
+      return ret;
+}
+
+opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
+{
+   OpusRepacketizer rp;
+   opus_int32 ret;
+   int i;
+   if (len < 1)
+      return OPUS_BAD_ARG;
+   opus_repacketizer_init(&rp);
+   ret = opus_repacketizer_cat(&rp, data, len);
+   if (ret < 0)
+      return ret;
+   /* Discard all padding and extensions. */
+   for (i=0;i<rp.nb_frames;i++) {
+      rp.padding_len[i] = 0;
+      rp.paddings[i] = NULL;
+   }
+   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0, NULL, 0);
+   celt_assert(ret > 0 && ret <= len);
+   return ret;
+}
+
+int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
+{
+   int s;
+   int count;
+   unsigned char toc;
+   opus_int16 size[48];
+   opus_int32 packet_offset;
+   opus_int32 amount;
+
+   if (len < 1)
+      return OPUS_BAD_ARG;
+   if (len==new_len)
+      return OPUS_OK;
+   else if (len > new_len)
+      return OPUS_BAD_ARG;
+   amount = new_len - len;
+   /* Seek to last stream */
+   for (s=0;s<nb_streams-1;s++)
+   {
+      if (len<=0)
+         return OPUS_INVALID_PACKET;
+      count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
+                                     size, NULL, &packet_offset, NULL, NULL);
+      if (count<0)
+         return count;
+      data += packet_offset;
+      len -= packet_offset;
+   }
+   return opus_packet_pad(data, len, len+amount);
+}
+
+opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
+{
+   int s;
+   unsigned char toc;
+   opus_int16 size[48];
+   opus_int32 packet_offset;
+   OpusRepacketizer rp;
+   unsigned char *dst;
+   opus_int32 dst_len;
+
+   if (len < 1)
+      return OPUS_BAD_ARG;
+   dst = data;
+   dst_len = 0;
+   /* Unpad all frames */
+   for (s=0;s<nb_streams;s++)
+   {
+      opus_int32 ret;
+      int i;
+      int self_delimited = s!=nb_streams-1;
+      if (len<=0)
+         return OPUS_INVALID_PACKET;
+      opus_repacketizer_init(&rp);
+      ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
+                                     size, NULL, &packet_offset, NULL, NULL);
+      if (ret<0)
+         return ret;
+      ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
+      if (ret < 0)
+         return ret;
+      /* Discard all padding and extensions. */
+      for (i=0;i<rp.nb_frames;i++) {
+         rp.padding_len[i] = 0;
+         rp.paddings[i] = NULL;
+      }
+      ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0, NULL, 0);
+      if (ret < 0)
+         return ret;
+      else
+         dst_len += ret;
+      dst += ret;
+      data += packet_offset;
+      len -= packet_offset;
+   }
+   return dst_len;
+}